Chapter 7 适配器模式

来源:互联网 发布:bat java工程师面试题 编辑:程序博客网 时间:2024/06/06 04:30

1 概述

适配器(Adapter)模式把某个类的接口转换成客户端所需要的另外一个接口,从而使得因接口不匹配无法一起工作的类功能顺利的一起工作。和其它设计模式一样,适配器模式也是从现实生活中抽象出来的。以电器为例,电视机的插头一般都是三相的,即阴极,阳极及地极,而有些房间的电源插座却只有两相,没有地极。因此,电源插座和电视机插头直接不匹配造成电视机无法使用。这时候,如果有一个插排完成两项到三相的转换就可以解决这个问题。这里的插排就可以理解成适配器。

2 实现方式

适配器模式一般涉及三种角色,即:

(1)目标角色(Target):这就是所期待得到的接口

(2)源角色(Adaptee):需要适配的接口

(3)适配器角色(Adapter):适配器类,该模式的核心,负责把源接口转换成目标接口。这一角色不可以是接口,而必须是具体的类

适配器模式在实现方式上可分成类适配器和对象适配器两种。

2.1 类适配器

类适配器模式主要是把源角色的API转换成为目标角色的API,参考下面的代码:

/** * 目标角色:电器接口,需要两相电和三相电两个接口 */interface ElectricalApplicance {     void twoPhasePowerSupply();     void threePhasePowerSupply();} /** * 源角色:插座类,只实现了两相电接口 */class Socket {     public void twoPhasePowerSupply() {        System.out.println("插座提供两相电接口");    }} /** * 适配器角色:插排类,继承自插座类并实现了电器接口 */class PowerStrip extends Socket implements ElectricalApplicance {     @Override    public void threePhasePowerSupply() {        System.out.println("插排另外提供三相电接口");    }}

其中,电器接口为目标接口,需要实现两相电和三相电的接口(两相电和三相电的电器都有)。而源角色插座类只有两相电接口的实现,适配器角色插排类通过继承插座类获得两相电的接口实现并自行实现了三相电的接口。这里,适配器角色充当了中间者的角色,而适配器角色和源角色之间的继承关系决定了这种模式是类适配器模式。

类适配器模式的UML类图如下:

2.2 对象适配器

对象适配器和类适配器的原理一样,都是通过适配器角色扮演中间者角色,将源角色的API转换成目标角色API。和类适配器模式不同的是,对象适配器模式将适配器角色和源角色之间的继承关系改成了关联关系,参考下列代码:

/** * 目标角色:电器接口,需要两相电和三相电两个接口 */interface ElectricalApplicance {     void twoPhasePowerSupply();     void threePhasePowerSupply();} /** * 源角色:插座类,只实现了两相电接口 */class Socket {     public void twoPhasePowerSupply() {        System.out.println("插座提供两相电接口");    }} /** * 适配器角色:插排类,继承自插座类并实现了电器接口 */class PowerStrip implements ElectricalApplicance {         private Socket socket;         public PowerStrip(Socket socket) {        this.socket = socket;    }     @Override    public void twoPhasePowerSupply() {        socket.twoPhasePowerSupply();    }     @Override    public void threePhasePowerSupply() {        System.out.println("插排另外提供三相电接口");    }}

对象适配器模式的UML类图如下:

2.3 缺省适配模式

和类适配器模式与对象适配器模式不同,缺省适配器模式严格意义上来说并不是一种适配器模式。因为,适配器模式的设计初衷是为了完成接口的转换,使接口能正常工作。而缺省适配器模式是给某个接口(该接口需要实现的方法很多)提供一个缺省的实现,这样实现该接口时就不需要一一实现其中的所有方法了,只需要继承这个缺省的实现,然后复写想要实现的方法即可。

缺省适配器模式在awt中被广泛使用。例如,MouseListener接口中需要实现mouseClicked,mousePressed等5个方法,而适配器类MouseAdapter提供了缺省实现(也称平庸的实现)。那么在添加鼠标监听器时只需要用MouseAdapter就可以了,例如下面的实现(通常配合匿名对象实现):

Panel panel = new Panel();panel.addMouseListener(new MouseAdapter(){    public void mouseClicked(MouseEvent e) {        System.out.println("Mouse Clicked: (" + e.getX() + ", " + e.getY() +")");    }});

3 总结

使用模式适配器,可以让系统具有更好的复用性和扩展性,即系统需要使用某个类,而该类的接口不符合要求,那么通过适配器模式就可以让这些功能得到更好的复用,并同时在实现适配器功能的时候,可以调用已开发好的功能来扩展现有的系统。

但是,凡事都是有两面性的,如果过多的使用适配器模式,会让系统变得非常的零乱且不易把控。例如,原本希望调用的是接口A,却在内部被适配成了接口B的实现,有时候这会让人非常的疑惑。因此,在使用适配器模式时,需要整体考虑系统的特性,合理使用适配器模式。




0 0