设计模式之适配器模式(换个包装再度利用)
适配器模式(Adapter Pattern)有时候也称包装样式或者包装。将一个类的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类工作在一起,做法是将类别自己的接口包裹在一个已存在的类中。
Adapter Pattern有两种:
- 类的Adapter Pattern(继承)
- 对象的Adapter Pattern(委托)
它们的类图分别为:
类适配器模式类图
对象适配器模式类图
就是将上图的Target接口改成抽象类,并被Adapter继承。
下面我们用第一种来实现适配器模式:
我们首先来看看类图:
具体实现如下:
Banner类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 + "*"); } }
Print接口类:
public interface Print { public abstract void printWeak(); public abstract void printStrong(); }
PrintBanner类:(发挥适配器的功能,先继承Banner在实现Print接口,然后继承其Banner的两个方法并实现Print接口的两个方法)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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(); } }
Main类:(利用前面所建立的PrintBanner类(即适配器功能)减弱(小括号)、或增强(前后一个*)字符串Hello后再输出)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class Main { public static void main(String[] args) { Print p = new PrintBanner("Hello"); p.printWeak(); p.printStrong(); } }
最后运行程序的结果为:
请注意,这里是把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源进行适配。
文章出处:http://www.cnblogs.com/scetopcsa/
欢迎关注微信公众号:yilu_yiyou(一路一游),一个不仅仅是代码的世界!
如果文中有什么错误,欢迎指出。以免更多的人被误导。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。