适配器模式(Adapter)
适配器,就像我们把家用的交流100V电压通过充电器转为直流5V的充电电压一样,是为了让现有的程序和所需的程序相适应而存在的。适配器模式(Adapter Pattern)有以下两种模式:
-
类适配器模式(使用继承的适配器)
-
对象适配器模式(使用委托的适配器)
一般在适配器模式中会有以下几个角色:
-
Target,定义所需的方法,类比上面提到的直流5V电压,对应下面示例中的Print接口
-
Client,使用Target所定义的方法进行具体处理,类比上面使用充电器的“我”,对应AdapterMain
-
Adaptee(被适配),类比上面所提的“现有的程序”,100V交流电压,对应下面的Banner
-
Adapter(适配器),类比充电器,对应PrintBanner
类适配器模式(继承)的类图:
对象适配器模式(委托)的类图:
使用了类适配器模式的示例程序(继承):加粗与弱化显示文本程序
-
类图:
-
Banner
类,类比家用的交流100V交流电压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
接口,“需求”的接口,类比我们所需的直流5V充电电压public interface Print { public abstract void printWeak(); public abstract void printStrong(); }
-
PrintBanner
类,扮演适配器的角色,将现有的Banner
经过一定处理,满足我们的需求Print
public class PrintBanner extends Banner implements Print { public PrintBanner(String string) { super(string); } @Override public void printWeak() { showWithParen(); } @Override public void printStrong() { showWithAster(); } }
-
AdapterMain
类,AdapterMain
不必知道PrintBanner
是如何实现的,这样就可以在不改动AdapterMain
的情况下修改PrintBanner
以实现其他的效果。注意前提是,使用Print类型来接收一个实现了Print
接口的类实例。public class AdapterMain { public static void main(String[] args) { Print p=new PrintBanner("This is adapter pattern"); p.printWeak(); p.printStrong(); } }
使用了对象适配器模式的示例程序(委托):加粗与弱化显示文本程序
-
类图:
-
与类适配器所不同的只有
PrintBanner
类,此时与Banner
类不再是继承关系,而改为聚合关系。PrintBanner
通过调用Banner
的方法来处理逻辑。public class PrintBanner { private Banner banner; public PrintBanner_extrust(Banner banner) { this.banner = banner; } public void printWeak() { banner.showWithParen(); } public void printStrong() { banner.showWithAster(); } }
为什么要使用适配器模式?
-
适配器模式可以将现有的已经充分测试过的bug少的类作为组件重复利用,已生成新的类。当新类出现问题的时候,我们也可以将Bug的范围确定在Adaptee之外,而只需要去检查测试Adapter即可
-
适配器模式可以处理版本升级与兼容性问题。比如让新版本扮演Adaptee角色,旧版本扮演Target角色,编写一个Adapter角色的类,负责用新版本的类来实现旧版本的类中的方法。