JAVA设计模式--适配器模式

1、什么是适配器模式

适配器(Adapter)模式又叫做包装( Wrapper )模式,是由GOF提出的23种设计模式中的一种结构型设计模式,Adapter模式的设计意图:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。


2、适配器模式的结构

适配器模式分为类适配器模式(采用继承方式实现)、对象适配器模式(采用对象组合方式实现)和接口适配器模式三种。

类适配器通过继承对一个类与另一个接口进行匹配,如下图所示。

类适配器模式涉及的角色及其职责如下:
客户端(Client)类:该类需要与符合条件的特定的接口协同工作。
目标(Target)接口类:客户端所需要的接口,在类适配器模式下该角色只能是接口。
适配者(Adaptee)类:需要被适配的类,适配者类一般是一个具体类,包含了客户端希望使用的某些业务方法。
适配器(Adapter)类:该类对适配者类和目标接口进行适配,在类适配器模式下通过继承方式实现,即:Adapter 继承 Adaptee 并实现Target接口。

类适配器模式结构示意源代码如下:
Target目标接口类是Client客户端类所需要的与特定领域相关的接口。

public interface Target {
 // Adaptee适配者有此方法的实现,但方法名可以不同
 void specificOperation();
 // Adaptee适配者没有的其他方法
 void otherOperation();
}

// Adaptee适配者类包含了客户端希望使用的某些业务方法,但Adaptee类不符合Client类所需的接口要求

public class Adaptee {
    public void operation() {
        System.out.println("执行Adaptee的operation()方法...");
    }
}

Adapter适配器类继承Adaptee适配者类并实现Target接口,这样 Adapter 既符合 Client 所需接口的要求,又可以继承原属于 Adaptee 的方法。

public class Adapter extends Adaptee implements Target {
     @Override
     public void specificOperation() {
         this.operation();
     }
     @Override
     public void otherOperation() {
         System.out.println("执行Adapter的otherOperation()方法...");
     }
}

为简单起见我们为 Client 添加一个 clientOperation()方法,该方法需要传入一个Target接口对象,在该Target接口对象中我们要复用现有的 Adaptee 的方法

public class Client {
    public static void clientOperation(Target target) {
        target.specificOperation();
        target.otherOperation();
    }

    public static void main(String[] args) {
        Adapter adapter = new Adapter();
        clientOperation(adapter);
    }
}
运行程序打印结果如下:
执行Adaptee的operation()方法...
执行Adapter的otherOperation()方法...
对象适配器通过组合对一个类及其子类与另一个接口进行匹配。

对象适配器模式涉及的角色及其职责如下:
客户端(Client)类:该类需要与符合条件的特定的接口协同工作。
目标(Target)接口类:客户端所需要的接口,在对象适配器模式下该角色可以是接口、抽象类或者非final的具体类。
适配者(Adaptee)类:需要被适配的类,适配者类一般是一个具体类,包含了客户端希望使用的某些业务方法。
适配器(Adapter)类:该类对适配者类和目标接口进行适配,在对象适配器模式下通过组合方式实现,即:Adapter 类继承 Target 类或者实现 Target 接口,并在其内部包含一个 Adaptee 对象的引用,通过对其内部的 Adaptee 引用的方法调用实现客户端所需要的接口。 

接下来以 Target 为接口的情况举例,对象适配器模式结构示意源代码如下:

Target 是 Client 所需要的与特定领域相关的接口。
public interface Target {
    // Adaptee适配者有此方法的实现,但方法名可以不同
    void specificOperation();
    // Adaptee适配者没有的其他方法
    void otherOperation();
}

Adaptee 包含了 Client 希望使用的某些业务方法,但 Adaptee 不符合 Client 的接口要求。
public class Adaptee {
    public void operation() {
        System.out.println("执行Adaptee的operation()方法...");
    }
}

Adapter 实现 Target 接口,并在其内部包含一个 Adaptee 对象的引用,通过对其内部的 Adaptee 对象的方法调用来实现客户端所需要的接口。
public class Adapter implements Target {
    private Adaptee adaptee;
    public Adapter(Adaptee adaptee) {
        super();
        this.adaptee = adaptee;
    }
    @Override
    public void specificOperation() {
        this.adaptee.operation();
    }
    @Override
    public void otherOperation() {
        System.out.println("执行Adapter的otherOperation()方法...");
    }
}

同样的,Client 依旧要与一个 Target 接口协同工作,对Client进行简单修改。
public class Client {
    public static void clientOperation(Target target){
        target.specificOperation();
        target.otherOperation();
    }
    public static void main(String[] args) {
        Adapter adapter = new Adapter(new Adaptee());
        clientOperation(adapter);
    }
}
运行程序打印结果如下:
执行Adaptee的operation()方法...
执行Adapter的otherOperation()方法...

接口适配器模式又被叫作缺省适配器(DefaultAdapter)模式,DefaultAdapter 为一个接口提供缺省实现,这样需实现该接口的类就可以直接从 DefaultAdapter 进行扩展,而不必再从原有接口进行扩展。当原接口中定义的方法很多,而其中大部分方法又不被需要时,这种模式非常实用。由缺省适配器类(由于该类一般都只为接口提供缺省的空实现,所以该类一般都被定义为抽象类)直接实现接口,并为所有方法提供缺省实现。这样,如果有用户类需要实现该接口就可以直接继承适配器类,并只需实现感兴趣的方法就可以了。
 

缺省适配器模式涉及的角色及其职责如下:
目标(Target)接口类:用户类所需要实现的接口,定义有很多方法,但这些方法不一定全都被用户类所需要。
缺省适配器(DefaultAdapter)类:实现目标接口,并为所有接口方法提供缺省实现。
具体(ConcreteClass)用户类:用户类要实现目标接口,但是又用不到接口所规定的所有的方法。
类适配器模式结构示意源代码如下:
Target接口类是用户类所需要实现的接口,该接口定义有很多方法。

目标(Target)接口类
public interface 和尚 {
    public void 吃斋();
    public void 念经();
    public void 打坐();
    public void 撞钟();
    public void 习武();
    public String getName();
}

// 缺省适配器(DefaultAdapter)类
public abstract class 天星 implements 和尚 {
    public void 吃斋(){}
    public void 念经(){}
    public void 打坐(){}
    public void 撞钟(){}
    public void 习武(){}
    public String getName(){
        return null;
    }
}

// 具体(ConcreteClass)用户类
public class 鲁智深 extends 天星{
    public void 习武(){
        拳打镇关西;
        大闹五台山;
        大闹桃花村;
        火烧瓦官寺;
        倒拔垂杨柳;
    }
    public String getName(){
        return "鲁智深";
    }
}


三、适配器模式的选择

通过使用适配器模式,我们可以达到以下目的:
5.1 复用现有的类,解决现有类和复用环境要求不一致的问题。
5.2 将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
5.3 一个对象适配器可以把适配者类和它的子类都适配到目标接口。

类适配器模式和对象适配器模式比较:
-类适配器通过继承方式来实现,是静态的;而对象适配器通过组合方式来实现,是动态的。
-对于类适配器,适配器直接继承自 Adaptee ,这使得适配器不能和 Adaptee 的子类一起工作。
-对于对象适配器,同一个适配器可以把 Adaptee 和它的子类都适配到目标接口。
-对于类适配器,适配器可以重定义 Adaptee 的部分行为,相当于子类覆盖父类的部分实现方法。
-对于对象适配器,要重定义 Adaptee 的行为比较困难,这种情况下,需要定义 Adaptee 的子类来实现重定义,然后让适配器组合子类。

原文:https://blog.csdn.net/pengjunlee/article/details/52347644 
 

猜你喜欢

转载自blog.csdn.net/jiangtianjiao/article/details/87944533