Adapter模式
在程序世界中,经常会存在现有的程序无法直接使用,需要做适当的变换后才能使用的情况。这种用于填补“现有的程序”和“所需的程序”之间差异的设计模式就是Adapter模式
Adapter模式分为两种:
- 类适配器模式(使用继承的适配器)
- 对象适配器模式(使用委托的适配器)
使用继承的适配器
示例
Banner类是现有的程序,Print接口则是所需的程序,PrintBanner类则是我们的适配器。该类继承了Banner并实现了“需求”--Print接口
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 + "*");
}
}
Print接口
public interface Print {
public abstract void printWeak();
public abstract void printStrong();
}
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");
p.printWeak();
p.printStrong();
}
}
这里将PrintBanner类的实例保存在了Print类型的变量中。在Main中,我们是使用Pring接口来编程的,对于Main类的代码而言,Banner类及其方法被完全隐藏起来,且Main并不知道PrintBanner是如何实现的,这样就可以在不用对Main类进行修改的情况下改变PrintBanner类的具体实现
使用委托的适配器
示例
在Java语言中,委托就是将某个方法中的实际处理交给其他实例的方法。
Main类与Banner类不变
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);
}
public void printWeak() {
banner.showWithParen();
}
public void printStrong() {
banner.showWithAster();
}
}
Adapter模式中的登场角色
Target(对象)
该角色负责定义所需的方法,即所需程序,在示例中,由Print接口(抽象类)扮演此角色
Client(请求者)
该角色负责使用Target角色所定义的方法进行具体处理,在示例中,由Main类扮演此角色
Adaptee(被适配)
Apaptee是一个持有既定方法的角色,即现有的程序,在示例中,由Banner类扮演此角色。
如果Adaptee角色中的方法与Target角色的方法相同,就不需要接下来的Adapter角色了。
Adapter(适配)
Adapter模式的主人公。使用Adaptee角色的方法来满足Target角色的需要,这就是Adapter模式的目的,也是Adapter角色的作用。在示例中,由PrintBanner类扮演这个角色。
类适配器模式的类图(使用继承)
对象适配器模式的类图(使用委托)
为什么要使用Adapter模式
如果某个方法就是我们所需要的方法,那么直接在程序中使用不就可以了,为什么还要考虑使用Adapter模式?
很多时候,我们并非从零开始编程,经常会用到现有的类。特别是当现有的类已经被充分测试过了,Bug很少,而且已经被用于其他软件中时,我们更愿意将这些类作为组件重复使用、
Adapter模式会对现有的类进行适配,生成新的类。通过该模式可以很方便地创建我们需要的方法群。当出现Bug时,由于我们很明确的知道Bug不在现有的类(Adaptee)中,所以只需检查Adapter角色的类即可。
此外,使用Adapter模式可以在完全不改变现有代码的前提下是现有代码适配于新的API。
当然,功能完全不同类是无法使用该模式的
Q.E.D.