GOF设计模式——Adapter模式
一、什么是Adapter模式?
Adapter模式,又称为适配器模式。
这是一个很通俗的名字,“适配器”,我们可以联想到笔记本电脑的充电器(专业名称又叫适配器),每一台笔记本电脑会对应只有一个适配器,适配器的作用是对民用的电压和电流进行转换,使得电压和电流满足当前的笔记本电脑的实际需求。那么,到了程序里面,又是怎么理解呢?我们可以将笔记本电脑实际的电压和电流当作是程序的需求,民用电压当作是程序原有情况,那么Adapter模式下的类就是充当这个充电器(适配器)。
二、Adapter模式的分类:
1、Class Adapter模式(使用继承)
所谓的Class Adapter模式就是使用继承的方式实现,就是当Target(需求)是一个接口时,就可以使用继承的方式。
2、Object Adapter模式(使用委托)
Object Adapter模式使用委托的方式,就是将具体实现交给别的对象执行。注意,这里的Tager(需求)已经是一个类,而不是一个接口,由于java只支持单继承的原则,所以对于Adaptee(实际情况),只能通过委托的方式交给Adapter调用。在Adapter类里面多了一个属性adaptee,这是Adaptee类的对象,通过这个对象来调用Adaptee里面的方法。
三、具体使用
1、Class Adapter模式
Main类:充当Client角色,用于使用Print的相关方法(即我要给笔记本电脑充电);
Print接口:充当Target角色,就是实际需求(即当前笔记本电脑只需要12V直流电压);
Banner类:充当Adaptee角色,就是实际情况(即当前只有民用220V交流电压);
PrintBanner类:充当Adapter角色,就是适配器类(即笔记本电脑充电适配器)。
- Print接口
public interface Print{
public abstract void printWerk();//打印削弱
public abstract void printStrong();//打印增强
}
- 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 + "*");
}
}
- PrintBanner类
public class PrintBanner extends Banner implements Print{
public PrintBanner(String string){
super(string);
}
public void printWeak(){
showWithParen();
}
public void printStrong(){
showWithAster();
}
}
- Main类
public class Main{
public static void main(String[] args){
Print p = new PrintBanner("hello world");
p.printWeak();
p.printStrong();
}
}
2、Object Adapter模式
上图的类的角色跟ClassAdapter模式的类的角色一样。
public abstract class Print{
public abstract void printWeak();
public abstract void printStrong();
}
- PringtManager
public class PrintBanner extends Print{
private Banner banner;
public PrintBanner(String string){
this.banner = new Banner(string);
}
public void printWeak(){
banner.showWithParen();
}
public void printStrong(){
banner.showWithAster();
}
}
Banner类和Main类跟Class Adapter模式的一样,这里不重复。
定位到main方法,上面两种模式的使用中,在main方法里都没有直接使用到Banner类的方法,也就是我需要给笔记本电脑充电(Print中的两个抽象方法),我根本不关心民用电压多少(Banner类的方法),只要使用这个特制的适配器(PrintBanner类),就可以满足我充电的这个动作需求。
四、Adapter模式应用场景
很多时候,我们并不是从零开始编写项目的,即这个项目已经设计了很多个类,或者经常使用已有的其他第三方类,而这些类往往已经被充分测试过,几乎没有bug,并且大量应用到程序的其他地方。如果现在为了适应业务发展,便有了新的需求,那么我们更愿意去通过对已有的类进行进一步的封装,生成新的类,这就是Adapter模式思想。
通过Adapter模式可以很方便地创建实际所需的方法群,当出现bug时,可以很明确的定位,迅速排除不是现有的类(即Adaptee类)。
对于软件的版本升级与兼容性,也可以应用Adapter模式。例如,假如现在只想维护新版本,这时可以让新版本扮演Adaptee角色,旧版本扮演Target角色,接着编写一个Adapter角色的类,这样子可以很好的解决新版本与旧版本兼容性的问题,而且只需要维护新版本就可以。
值得注意的是,当Target与Adaptee的功能完全不同的时候,使用Adapter模式就完全没有意义了。