结构型设计模式----适配器模式

简介

结构型设计模式

结构型设计模式描述如何将类和对象结合在一起形成更大的结构

分类:类结构型和对象结构型

  • 类结构型关心得是类的组合,由多个类组合成一个更大的系统,在类结构中一般存在继承和实现关系。
  • 对象结构型关心得是类和对象得组合,通过在一个类中定义另一个类得实例得方式将它们关联起来。一般用关联关系来代替继承,所以大多数结构型模式都是对象结构型。

适配器模式

今天要讲得适配器模式就是结构型设计模式的一种。
定义:将一个接口转化为客户希望的另一个接口,使得接口不兼容的类可以一起工作。

说明:在适配器模式中需要定义一个包装类,包装不兼容接口的对象,这个包装类就是适配器,被包装的就是适配者。

模式动机:将客户的请求转化为适配者的相应接口的调用。也就是说:在客户类调用适配器的方法时,适配器将会在内部调用适配者的方法,这个过程对客户类来说是透明的,客户类并不直接访问适配者的方法。
根据结构可以分为类适配器和对象适配:
类适配器:
在这里插入图片描述
对象适配器:
在这里插入图片描述
模式结构说明:
Target:用户所期望的接口,可以是抽象类也可以是一个接口。
Adapter:适配器类对Adaptee和Target的进行适配,是适配器模式的核心。
Adaptee:适配者类,即被适配的类。
Client:客户端

类适配器模式

首先是目标类(或接口)Target

public interface Target {
    void request();
}

适配者类Adaptee

public class Adaptee {
    public void adapteeRequest() {
        System.out.println("被适配类的方法。。。");
    }
}

类适配器

public class Adapter extends Adaptee implements Target {

    @Override
    public void request() {
        super.adapteeRequest();
    }
}
public class Test {
    public static void main(String[] args) {
        Target t = new Adapter();
        t.request();
    }
}
//输出:被适配类的方法。。。

对象适配器

目标类和适配者类是不变的,主要是适配器类结构的改变
对象适配器:

public class ObjectAdapter implements Target {
    private Adaptee adaptee;

    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    @Override
    public void request() {
        adaptee.adapteeRequest();
    }
}

测试:

public class Test {
    public static void main(String[] args) {
        Target t = new ObjectAdapter(new Adaptee());
        t.request();
    }
}
//结果:被适配类的方法。。。

缺省适配器模式

上面说到的情况都是很简单的,适配者类仅有很少的方法,而且都是有用的。假如现在有一个适配者接口:

interface NewAdaptee {
    void sing();
    void dance();
    void rap();
    void basketball();
    void run();
}

存在有很多的方法,而且都没有实现。如果我们使用上面的类适配器模式的话就需要实现全部的方法。但是我现在的新目标接口是这样的:

interface NewTarget {
    void singer();
}

我只对sing感兴趣,那么就多做了很多不必要的工作。这个时候就引入了缺省适配器的概念,用一个抽象类实现该目标接口,为每一个方法提供默认实现(空方法)。也可以有选择的实现一些方法,根据具体的业务考虑。具体的适配器则继承这个抽象类来实现目标接口。
缺省适配器:

abstract class DefultAdapter implements NewAdaptee {
    public void sing() {}
    public void dance() {}
    public void rap() {}
    public void basketball() {}
    public void run() {}
}

具体适配器:

class SpecificAdapter extends DefultAdapter implements NewTarget {
    public void sing() {
        System.out.println("我会唱歌。。。");
    }
    public void singer() {
        this.sing();
    }
}

测试:

public class Test {
    public static void main(String[] args) {
        NewTarget t = new SpecificAdapter();
        t.singer();
    }
}
//输出:我会唱歌。。。

在JDK类库的java.awt.event中广泛使用了缺省适配器模式,比如WindowAdapter、KeyAdapter等
我们来看WindowListener:

public interface WindowListener extends EventListener {
    public void windowOpened(WindowEvent e);
    public void windowClosing(WindowEvent e);
    public void windowClosed(WindowEvent e);
    public void windowIconified(WindowEvent e);
    public void windowDeiconified(WindowEvent e);
    public void windowActivated(WindowEvent e);
    public void windowDeactivated(WindowEvent e);
}

如果直接使用实现该接口的方式,就不得不处理一些其他的用不到的方法。而使用缺省的适配器WindowAdapter就方便多了
WindowAdapter:

public abstract class WindowAdapter
    implements WindowListener, WindowStateListener, WindowFocusListener
{
    public void windowOpened(WindowEvent e) {}
    public void windowClosing(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowActivated(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}
    public void windowStateChanged(WindowEvent e) {} 
    public void windowLostFocus(WindowEvent e) {}
}

通过继承缺省适配器的方式只需要实现自己感兴趣的方法即可。

优缺点比较

首先说适配器本身具有的优点:

  • 将目标类和适配者类解耦
  • 增加了类的透明性和复用性。客户端看不到适配者类接口转换为目标接口的过程,对客户端来说是透明的。
  • 灵活性和扩展性好。可以更换适配器来完成不同的需求

对于类适配器来说:

  • 优点:可以重写适配者类的一些方法,更加灵活
  • 缺点:对于单继承的语言,如java,具有一定局限

对于对象适配器来说:

  • 优点:可以适配多个适配者
  • 缺点:如果要重写适配者的一些方法过程就比较复杂了,先要作一个适配者类的子类,然后修改方法。适配器去适配这个子类才可以,过程比较复杂。

适用场景

  1. 系统要使用一些现有的类,但是这些类的接口不满足需要。
  2. 建立一个可重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。(就是用适配器去适配不同的类接口)

那适配器模式就到这里了,讲的干巴巴的,以后用尝试新的方式帮助大家理解和记忆。

文章的不足和错误,欢迎大家留言指出!

猜你喜欢

转载自blog.csdn.net/machine_Heaven/article/details/105027996