首页 > 代码库 > 设计模式之适配器模式

设计模式之适配器模式

适配器模式(Adapter Pattern)有时候也称包装样式或者包装。将一个类的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类工作在一起,做法是将类别自己的接口包裹在一个已存在的类中。

Adapter Pattern有两种

  1. 类的Adapter Pattern(继承)
  2. 对象的Adapter Pattern(委托)

下面我们用第一种来实现适配器模式:

我们首先来看看类图:

 

具体实现如下:

Banner类:

public class Banner {
    private String string;

    public Banner(String string) {
        this.string = string;
    }

    public void showWithParen() {
        System.out.println("(" + string + ")");
    }

    public void showWithAster() {
        System.out.println("*" + string + "*");
    }

}
View Code

Print接口类:

public interface Print {
    public abstract void printWeak();

    public abstract void printStrong();

}

PrintBanner类:(发挥适配器的功能,先继承Banner在实现Print接口,然后继承其Banner的两个方法并实现Print接口的两个方法)

public class PrintBanner extends Banner implements Print {

    public PrintBanner(String string) {
        super(string);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void printWeak() {
        showWithParen();

    }

    @Override
    public void printStrong() {
        showWithAster();

    }

}
View Code

Main类:(利用前面所建立的PrintBanner类(即适配器功能)减弱(小括号)、或增强(前后一个*)字符串Hello后再输出)。

public class Main {

    public static void main(String[] args) {
        Print p = new PrintBanner("Hello");
        p.printWeak();
        p.printStrong();

    }

}
View Code

最后运行程序的结果为:

请注意,这里是把PrintBanner的对象实例指定到Print接口类型的变量。Main类只不过是利用Print这个接口来写程序而已。从Main类的源代码完全看不出有Banner类、showWithParen方法或showWithAster方法。就好像是笔记本电脑只要有人提供12V直流电的电流就能正常运行,根本不知道它的原形(适配器的另一端)竟然是220V交流电。

 

前面的程序使用“类”的Adapter Pattern,下面我们用第二种方法来实现:

我们首先依然来看看类图:

同第一种方法相比,只需修改Print类和PrintBanner类即可,其余的类同第一种方法相同:

Print类:

public abstract class Print {
    public abstract void printWeak();

    public abstract void printStrong();

}

PrintBanner类:

public class PrintBanner extends Print {
    private Banner banner;

    public PrintBanner(String string) {
        this.banner = new Banner(string);
    }

    @Override
    public void printWeak() {
        banner.showWithParen();

    }

    @Override
    public void printStrong() {
        banner.showWithAster();

    }

}

其运行结果同第一种相同:

Addapter Pattern 中所出现过的参与者可整理如下:

Targer(对象)参与者

  在程序示例中,负责这个参与者的是Print接口(继承)和Print类(委托)

Client (委托人)参与者

  利用对象参与者的方法来做事的参与者,在程序示例中,负责这个参与者的是Main类。

Adaptee(被动符合)参与者

  在程序示例中,负责这个但与这的是Banner类。如果担任Adptee参与者的方法与Target参与者的方法相符时,那就不需要后面的Adapter参与者了。

Adapter(主动符合)参与者

  利用Adaptee参与者的方法努力满足Targetc参与者的要求是Adapter Pattern 的使命,这是Adapter参与者的工作。在程序示例中,负责这个参与者的是PrintBanner类。如果是类的Adapter Pattern,Adapter参与者要通过“继承”的方式来利用Adaptee参与者。

 

适用性:

 

1. 系统需要使用现有的类,而此类的接口不符合系统的需要。

 

2. 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。这些源类不一定有很复杂的接口。

 

3. (对对象适配器而言)在设计里,需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器,而这不太实际。

 

 

效果及优缺点:

对于类适配器:

 

1. 用一个具体的Adapter类对Adaptee和Taget进行匹配。结果是当我们想要匹配一个类以及所有它的子类时,类Adapter将不能胜任工作。

 

2. 使得Adapter可以override(重定义) Adaptee的部分行为,因为Adapter是Adaptee的一个子类。

 

对于对象适配器:

 

1. 允许一个Adapter与多个Adaptee,即Adaptee本身以及它的所有子类(如果有子类的话)同时工作。Adapter也可以一次给所有的Adaptee添加功能。

 

2. 使得override(重定义)Adaptee的行为比较困难。如果一定要override Adaptee的方法,就只好先做一个Adaptee的子类以override Adaptee的方法,然后再把这个子类当作真正的Adaptee源进行适配。