摘要:本文用一个实例场景描述Gof 23设计模式中的适配器(变压器)模式,并用Quarkus框架代码给予实现,同时也给出实现代码的UML模型。
关键字:Gof 23 设计模式 适配器模式 Quarkus
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.Quarkus的实现程序代码
Quarkus程序实现主要包括Customer类文件、Analyst类文件和Designer类文件等3个文件。其关系如图3所示。下面分别列出这3个文件的程序代码,最后列出测试代码并显示输出结果。
Customer类文件程序代码清单01所示。
程序代码清单01
@ApplicationScoped
public class Customer {
private String customerName;
private String requirement = null;
//public Customer(){}
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(){}
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
@ApplicationScoped
public class Designer {
private String designerName ;
private String works = null;
private String Designs = null;
public Designer(){ }
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 AdapterClient implements QuarkusApplication {
@ConfigProperty(name = "gof23.structuralpattern.adapter.title", defaultValue = "gof23")
String title;
@Inject Customer customer;
@Inject Designer designer ;
@Override
public int run(String... args) {
System.out.println("————" + title + "演示输出——————");
customer.setCustomerName("客户小王");
customer.setRequirement("客户小王的需求");
designer.setName("开发员小张");
Analyst analyst = new Analyst("分析员小刘");
//客户把用户需求提交给分析员
analyst.setRequest(customer.commitRequirement());
//分析员经过转化后提供给开发人员
analyst.setDesigner(designer);
//得到满足客户的需求的工作产品
System.out.println(analyst.getFinishworks());
return 0;
}
public static void main(String... args) {
Quarkus.run(AdapterClient.class, args);
}
}
适配器模式测试类输出结果如下所示:
————用户提交需求————
————分析员按照用户需求转化为需求分析和设计————
————按照需求分析设计转化为具体工作————
分析员小刘按照客户小王的需求,形成需求设计内容。开发员小张按照需求设计内容,完成工作。
4. 相关Quarkus程序源码下载
可以直接从github上获取代码,读者可以从github上clone预先准备好的示例代码。
git clone https://github.com/rengang66/quarkus-sample-gof23.git
这是一个Maven项目,然后Maven导入工程。该程序位于“src\main\java\com\iiit\quarkus\sample\gof23\structuralpattern\adapter”目录中。
同时也可以从gitee上clone预先准备好的示例代码,命令如下:
git clone https://gitee.com/rengang66/quarkus-sample-gof23.git
参考文献
[1] E.Gamma, R.Helm, R.Johnson, and Vlissides. Design Patterns Elements of Reusable Object Oriented Software. Addison-Wesley, 1995
[2] E.Gamma, R.Helm, R.Johnson, and Vlissides.著,李英军等译,设计模式:可复用面向对象软件的基础,北京:机械工业出版社.2000.9.
[3] 阎宏,Java与模式,北京:电子工业出版社. 2002.10
[4] 王俊峰 戚晓滨. 设计模式和UML. 计算机应用研究,1999.16(5), 27-29,39.
[5] 陈琴 朱正强. UML在设计模式描述中的应用. 计算机工程与设计,2003.24(4), 81-84.
[6] 郭庆华 刘镰斧. 设计模式在网元管理系统的应用. 福建电脑,2005.(12),31-31,22.
[7] 马维达. ACE与GoF设计模式——Adapter模式在ACE内存管理类中的应用. 程序员,2003.(10), 92-93.
[8] 李忠慧. 基于Z的适配器模式形式化描述. 福建电脑,2008.24(7), 80-80,100.
[9] 陈丁山. 设计模式的研究与应用. 电脑知识与技术,2007.(23), 1346-1348.
[10] 赵永明 郭敏. 设计模式在雷达终端软件系统中的应用. 火控雷达技术,2008.(2), 93-96.
[11] 张晓怀 陈业初 寇蔚. 设计模式在设备故障红外智能诊断软件中的应用. 机电设备,2007.24(11), 29-33,13.
[12] 鲁江 夏雨人. 适配器模式及其应用. 微型电脑应用,2007.23(7), 59-61.
[12] 洪中. 组态软件设计中的模式应用. 微计算机信息,2007.(28), 279-281.
[13] 王莉 汤灵愈. 基于设计模式的遗传算法类库的框架模型. 科技创新导报,2008.(3), 7-8.
[14] 肖志峰 龚健雅 王艳东 翟晓芳. 面向对象的软件设计模式在配电GIS中的应用. 测绘信息与工程,2005.30(3), 3-5.
[15] 叶建平. 设计模式在游乐设施检测管理信息系统中的应用. 微计算机信息,2005.21(12X), 213-214,77.
[16] Quarkus官网. https://quarkus.io/