设计模式之适配器模式
适配器模式,将一个类的接口转换成用户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。它可以使得原本不兼容的事物能够协同工作,而无需修改现有事物的内部结构。
适配器模式结构图
代理模式包含Target(目标抽象类),Adapter(适配器类)和Adaptee(适配者类)。
Target(目标抽象类):定义了客户想要用的特定接口,可以是个抽象类或者接口,也可以是具体的类。Adapter(适配器类):适配者类可以调用另一个接口,作为一个转换器,对Adaptee
和Target
进行适配。对象适配器,它通过实现Target
接口并关联一个Adaptee
对象来产生关联。Adaptee(适配者类):适配者就是被设配的角色,它定义了一个已经存在的接口,改接口需要适配,以达到重用的目的。
适配器模式示例
假设有一位老板,这里称呼这个老板为林老板,他的公司做海外业务的,因为做的是海外业务,所以不要听得懂英文,而林老板不会英语,于是林老板招聘了一个专业的英语翻译员。当与外国的客户沟通时,林老板说话,由翻译员用英语转述给客户,相反,国外客户说话,翻译员翻译成中文给林老板。在这个例子里,翻译员就相当于适配(Adapter),而老板就是调用者(Client),国外客户就是适配者类(Adaptee)。
**Target(目标抽象类)**的定义
/*Target(目标抽象接口定义)*/
public interface ITranslator {
/*翻译为中文*/
void translateToChinese();
}
Adaptee(适配者类)),需要被适配的对象,国外客户就是需要被适配的,这里使用英国客户,定义如下:
/*Adaptee(适配者类),国外客户,一个英国客户*/
public class BritishCustomer {
/*简单的模拟一句问候语*/
public String say(){
return "Hello,Boss Lin!";
}
}
Adapter(适配器类),是翻译员,她主要将英文翻译成中文给林老板,适配者类的实现如下:
/*Adapter(适配者类),英语翻译员*/
public class EnglishTranslator implements ITranslator {
private BritishCustomer britishCustomer;
public EnglishTranslator(BritishCustomer britishCustomer) {
this.britishCustomer = britishCustomer;
}
@Override
public void translateToChinese() {
/*翻译为中文*/
String someEnglish = britishCustomer.say();
if (someEnglish.equalsIgnoreCase("Hello,Boss Lin!")){
//翻译
System.out.println("翻译,约翰:你好,林老板! ");
}
}
}
测试类,BossLin
作为测试的调用,实现如下:
/*调用者,需要通过翻译员来与国外客户沟通*/
public class BossLin {
private ITranslator translator;
public BossLin(ITranslator translator) {
this.translator = translator;
}
public void say(String text){
System.out.println(text);
}
public void listen(){
translator.translateToChinese();
}
/*测试入口*/
public static void main(String[] args) {
BritishCustomer britishCustomer = new BritishCustomer();
ITranslator translator = new EnglishTranslator(britishCustomer);
BossLin bossLin = new BossLin(translator);//Boss Lin需要这个适配器
//<1> 林老板问候一句
bossLin.say("林老板:你好,约翰!");
//<2> 林老板听对方响应,由翻译员(适配器)进行翻译
bossLin.listen();
}
}
测试程序执行结果:
什么场景下使用适配器模式
使用该模式的前提是不能或者不想修改原来的适配者类接口和目标对象类接口,这样就可以使用已有的实现来实现所需的接口,否则,如果都能够修改或者想要修改原有的实现,那完全没有必要使用适配器模式。适配器模式就是为了不改变目标接口定义和已有适配者接口的实现,通过适配的方式,将已有的实现适配到用户需要的接口中。例如:我们定义了一个接口A(方法),发现第三方库有个接口B已经实现了接口A实现,但是我们不想重新修改接口A(方法)的定义,因为系统中很多地方已经使用了接口A(方法),我们不想修改接口A的定义,那么就可以通过适配器模式,完成接口A到第三方系统提供的接口B的实现。
适配器模式优缺点
优点:
-
将目标类和适配者类解耦
-
增加了类的透明性和复用性
缺点:
-
类适配器,对于
Java、C#
等不支持多重继承的语言,不能将一个适配者类和他的子类同时适配到目标接口。 -
对象适配器,要想置换**Adaptee(适配者类)**的方法比较难。
总结
适配器模式是一种比较简单的模式,它主要解决的新旧接口之间的兼容问题,或者重用某些已有实现且不想更改已有的接口定义,这是使用适配器模式可以事半功倍。