1 基础知识
1.1 标准定义
适配器模式标准定义:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
1.2 分析和说明
适配器模式属于结构型设计模式。把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配器模式也叫变压器模式,也叫包装器(Wrapper)模式。
当一个类需要另一个类的方法,但是这两个类并兼容。从实现原理上来看.达到这一目的的方法有两种:一种是继承,一种是对象组合。第一种方法中.从一个非一致性的类中派生一个新类,并增加新的方法使派生类与所需接口匹配;第二种方法中.在新类中包含最初的类.并创建方法来解释新类中的调用.这两种方法即人们通常所俗称的类适配器和对象适配器。适配器可以采用类的适配器,也可以采用对象的适配器。
适配器(Adapter)模式结构如图1所示,包括的角色有目标(Target)角色、源(Adaptee)角色和适配器(Adapter)角色。
图1 适配器模式结构
目标(Target)角色:这就是所期待的接口,定义了客户所期望的操作。目标(Target)角色可以是具体类或抽象类。该角色不可缺少。
源(Adaptee)角色:这是我们原有的产品,也是需要被适配的产品。这是我们原有的产品,也是需要被适配的产品:源(Adaptee)角色可以用接口、抽象类和具体类来实现。该角色不可缺少。
适配器(Adapter)角色:适配器角色是本模式的核心。Adapter对Adaptee接口与Target接口进行适配,适配器把源接口转换成目标接口,在Target目标角色与Adaptee源角色之间提供一种过渡,即把Adaptee源角色所提供的接口转换为Target目标角色所提供的接口。适配器(Adapter)角色必须是具体类。该角色不可缺少。
2 应用场景举例
比如对于公司客户和公司的设计编码开发人员直接进行交流可能比较困难。但中间加一个需求分析人员就把事情搞得比较简单。客户把自己的想法告诉需求分析人员,需求分析人员把用户需求转化成需求分析,并告诉设计编码人员如何进行设计和实现。需求分析人员就是一个适配器,把两个毫不联系的人员匹配起来。在一些软件外包行业就是有这样的实际情况。用例分析见图2所示。
图2 适配器模式用例图
在这里可以把Customer类比作为目标(Target)角色,Designer类比作为源(Adaptee)角色,Analyst类比作为适配器(Adapter)角色。其实现类图如图3所示。Analyst类继承Customer类并关联Designer类。
图3 适配器模式类图
适配器模式实现的顺序图如图4所示,实现顺序描述:
① 创建一个Customer对象;
② 创建一个Analyst对象;
③ 创建一个Designer对象;
④ Customer对象调用commitResuirement方法,给Analyst提交需求;
⑤ Analyst获取需求并进行分析;
⑥ 把Designer对象赋值给Analyst,Analyst把分析后的需求给Designer对象;
⑦ Designer对象按照分析完成开发工作并返回给Analyst对象,Analyst对象把完成的工作给Customer对象。
图4 适配器模式实现顺序图
Customer对象和Designer对象由于不兼容而不能一起工作,但是中间加上了一个Analyst对象。Analyst对象把Customer对象的需求转化给Designer对象。接着Designer对象完成的工作内容转化给Customer对象。Analyst对象在里面起了一个“转化”(适配)的功能。
3.Java的实现程序代码
Java程序实现主要包括Customer类文件、Analyst类文件和Designer类文件等3个文件。其关系如图3所示。下面分别列出这3个文件的程序代码,最后列出测试代码并显示输出结果。
Customer类文件程序代码清单01所示。
程序代码清单01
public class Customer { private String customerName; private String requirement = null; public void setRequirement(String require) { requirement = require; } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } public String getRequirement() { return requirement; } public String commitRequirement() { System.out.println("————用户提交需求————"); return requirement; } } |
Analyst类文件程序代码清单02所示。
程序代码清单02
public class Analyst extends Customer { private String analystName; private Designer designer = null; private String request; public Analyst(String name) { analystName = name; } public String getName() { return analystName; } public void setName(String name) { this.analystName = name; } public Designer getDesigner() { return designer; } public void setDesigner(Designer designer) { this.designer = designer; } public void setRequest(String content) { request = content; } public String getFinishworks() { String designs = requestToDesign(); designer.setDesigns(designs); return designer.getFinishWork(); } public String requestToDesign() { System.out.println("————分析员按照用户需求转化为需求分析和设计————"); return getName() + "按照" + request + ",形成需求设计内容。"; } } |
Designer类文件程序代码清单03所示。
程序代码清单03
public class Designer { private String designerName; private String works = null; private String Designs = null; public Designer(String name) { designerName = name; } public String getFinishWork() { designToWorks(); return works; } public void setDesign(String Design) { Designs = Design; } public void designToWorks() { System.out.println("————按照需求分析设计转化为具体工作————"); works = Designs + getName() + "按照需求设计内容,完成工作。"; } public String getName() { return designerName; } public void setName(String name) { this.designerName = name; } public String getWorks() { return works; } public String getDesigns() { return Designs; } public void setDesigns(String designs) { Designs = designs; } } |
适配器模式测试程序的代码清单04如下:
程序代码清单04
public class Client { public static void main(String[] args) { Customer customer = new Customer(); customer.setCustomerName("客户小王"); customer.setRequirement("客户小王的需求"); Designer designer = new Designer("开发员小张"); Analyst analyst = new Analyst("分析员小刘"); // 客户把用户需求提交给分析员 analyst.setRequest(customer.commitRequirement()); // 分析员经过转化后提供给开发人员 analyst.setDesigner(designer); // 得到满足客户的需求的工作产品 System.out.println(analyst.getFinishworks()); } } |
适配器模式测试类输出结果如下所示:
————用户提交需求———— ————分析员按照用户需求转化为需求分析和设计———— ————按照需求分析设计转化为具体工作———— 分析员小刘按照客户小王的需求,形成需求设计内容。开发员小张按照需求设计内容,完成工作。 |
4 扩展和说明
适配器模式有几种变形。一种是依靠继承来变化,一种是依靠对象组合来变化。按照上面场景,还有变形为4种结构模式(图5所示)。
第1种结构 第2种结构 第3种结构 第4种结构
图5 适配器模式4种结构
第1种结构是Analyst类继承Customer类,然后关联Designer类。就是上述的应用场景结构。
第2种结构是Analyst类继承Designer类,然后关联Customer类。
第3种结构是Analyst类同时关联Designer类和Customer类。
第4种结构是Analyst类继承Designer类和Customer类。由于C++语言支持多重继承而java和C#不支持,所以,这种结构支持C++语言而不支持java和C#。
参考链接
7种结构型模式:
Gof23种设计模式(6)——适配器模式(Adapter)
Gof23种设计模式(7)——桥接模式(Bridge)
Gof23种设计模式(8)——组合模式(Composite)
Gof23种设计模式(9)——装饰器模式(Decorator)
Gof23种设计模式(10)——外观模式(Facade)
Gof23种设计模式(11)——享元模式(Flyweight)
Gof23种设计模式(12)——代理模式(Proxy)
Gof23种设计模式 —— 结构型模式总结和比较
回到总目录:Gof23种设计模式(全解析)
(转载自微信公众号:架构设计模式)