摘要:本文用一个实例场景描述Gof 23设计模式中的装饰模式,并用Quarkus框架代码给予实现,同时也给出实现代码的UML模型。
关键字:Gof 23 设计模式 装饰模式 Quarkus
1 基础知识
1.1 标准定义
装饰(Decorator)模式标准定义:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
1.2 分析和说明
装饰(Decorator)模式属于结构型设计模式。装饰模式用于动态地为对象附加额外的职责,以达到扩展其功能,是继承关系的一个替代方案,提供比继承更多的灵活性。动态给一个对象增加功能,这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。
Decorator结构如图1所示,角色包括抽象构件(Component)角色、具体构件(Concrete Component)角色、装饰(Decorator)角色和具体装饰(Concrete Decorator)角色。
图1 装饰模式结构
抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。抽象构件角色作为整个装饰模式类图体系的超类,其子类均可以被增添附加责任。
具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(Concrete Decorator)角色:负责给构件对象增添附加的责任。
2 应用场景举例
比如公司的软件工程都是由需求分析、设计、编码、测试、部署和维护组成。这只是一般过程,但是万一有的时候要加上需求分析验证,有的时候要加上设计验证等过程。就可以通过装饰模式来实现。软件工程过程是抽象构件角色:标准软件工程过程是具体构件角色:定义一个将要接收附加责任的类。附加验证是装饰角色。需求分析验证是具体装饰角色。应用场景的用例见图2。
图2 装饰模式用例图
在这里可以把AbstractProcess类理解为抽象构件(Component)角色。StandardProcess类是具体构件(Concrete Component)角色。AdditionalProcess类是一种装饰(Decorator)角色。DesignCheckProcess类和RequestVerificationProcess类是具体装饰(Concrete Decorator)角色。其实现类图如图3所示。AbstractProcess抽象类有两个子类,一个是StandardProcess类,另一个是AdditionalProcess类。AdditionalProcess类不仅仅继承AbstractProcess抽象类,而且还关联AbstractProcess抽象类。DesignCheckProcess类和RequestVerificationProcess类是继承AdditionalProcess类的子类,他们是附加类的具体实现。
图3 装饰模式类图
装饰模式实现如图4所示,实现顺序描述:① 创建一个StandardProcess对象,② 创建一个RequestVerificationProcess对象;③ 把RequestVerificationProcess对象赋值给StandardProcess对象;④ 调用RequestVerificationProcess对象的ConcreteActualProcess方法;⑤ 创建一个DesignCheckProcess对象;⑥ 把DesignCheckProcess对象赋值给StandardProcess对象;⑦ 调用DesignCheckProcess对象的ConcreteActualProcess方法;⑧ 显示StandardProcess对象最新的项目过程情况。
图4 装饰模式实现顺序图
对于增加项目过程的方式有两种,一种是直接在标准的项目过程中加入项目过程,还有一种是附加项目过程,然后接着在附加项目过程中加入项目过程。第一种方式要修改整个全局项目过程的内容,所以改动比较大,而采用第二种方式,只是修改附加项目过程,只是修改了部分内容。
3.Quarkus的实现程序代码
Quarkus程序实现主要包括AbstractProcess类文件,StandardProcess类文件,AdditionalProcess类文件,DesignCheckProcess类文件和RequestVerificationProcess类文件等5个文件。其关系如图3所示。下面分别列出这5个文件的程序代码,最后列出测试代码并显示输出结果。
AbstractProcess类程序代码清单01所示。
程序代码清单01
public abstract class AbstractProcess {
protected List<String> componentList = new ArrayList<String>();
public void addProcess(String processName){componentList.add(processName);}
public void showAllProcess(){
if (componentList == null){System.out.println("没有过程");}
for (int i=0; i<componentList.size(); i++){
System.out.print(componentList.get(i) + ";");
}
}
}
StandardProcess类程序代码清单02所示。
程序代码清单02
@ApplicationScoped
public class StandardProcess extends AbstractProcess{
public StandardProcess(){
initizeProcess();
}
private void initizeProcess(){
addProcess("需求分析过程");
addProcess("设计过程");
addProcess("编码过程");
addProcess("测试过程");
addProcess("部署过程");
addProcess("维护过程");
}
}
AdditionalProcess类程序代码清单03所示。
程序代码清单03
@ApplicationScoped
public class AdditionalProcess extends AbstractProcess{
protected AbstractProcess actualProcess;
public void setActualProcess(AbstractProcess actualProcess) {
this.actualProcess = actualProcess;
}
}
DesignCheckProcess类和RequestVerificationProcess类程序代码清单04所示。
程序代码清单04
@ApplicationScoped
public class DesignCheckProcess extends AdditionalProcess{
public void ConcreteActualProcess(){
actualProcess.addProcess("设计检查");
}}
@ApplicationScoped
public class RequestVerificationProcess extends AdditionalProcess{
public void ConcreteActualProcess(){
actualProcess.addProcess("需求验证");
}
}
装饰模式测试程序的代码清单05如下:
程序代码清单05
public class DecoratorClient implements QuarkusApplication {
@ConfigProperty(name = "gof23.structuralpattern.decorator.title", defaultValue = "gof23")
String title;
@Inject StandardProcess projectProcess;
@Inject RequestVerificationProcess projectAddProcess1;
@Inject DesignCheckProcess projectAddProcess2;
@Override
public int run(String... args){
System.out.println("——————" + title + "演示输出——————————");
System.out.println("——————项目的标准过程———————");
projectProcess.showAllProcess();
System.out.println();
//附加需求验证过程
projectAddProcess1.setActualProcess(projectProcess);
projectAddProcess1.ConcreteActualProcess();
System.out.println("——————增加需求验证过程后的项目过程———————");
projectProcess.showAllProcess();
System.out.println();
//附加设计检查过程
projectAddProcess2.setActualProcess(projectProcess);
projectAddProcess2.ConcreteActualProcess();
System.out.println("———再增加设计检查过程后的项目过程————");
projectProcess.showAllProcess();
return 0;
}
public static void main(String... args) {
Quarkus.run(DecoratorClient.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\decorator”目录中。
同时也可以从gitee上clone预先准备好的示例代码,命令如下:
git clone https://gitee.com/rengang66/quarkus-sample-gof23.git
5 扩展和说明
JDK中I/O 库中InputStream实现就是采用Decorator模式。在以Java的I/O系统中的输入流为有多种来源,有ByteArrayInputStream, FileInputStream, FilterInputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream等。其中ByteArrayInputStream对应字节数组,FileInputStream对应文件流,ObjectInputStream对应对象流,PipedInputStream对应管道流,StringBufferInputStream对应String对象流,SequenceInputStream对应流序列,FilterInputStream对应一些要求额外功能的数据处理流。
参考文献
[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] 王晓波 蔡汉明 王军 崔慧敏. 设计模式在线切割CAD软件开发中的应用. 机电工程技术,2006.35(2),44-47.
[7] 唐露萍 陈洁. 设计模式在短波通信软件中的应用. 计算机工程,2008.34(D09), 148-150.
[8] 张婧 朱晓民 廖建新. 基于设计模式对WV网关业务逻辑处理模块的重构. 计算机系统应用,2008.(10), [9] 谢倩 谭红星 尚光龙. 面向对象系统设计模式的选择与应用. 郑州轻工业学院学报:自然科学版,2008.23(2), 65-68.
[10] 常亮 杨宏伟. 设计模式在出/入库管理中的应用研究. 唐山学院学报,2008.21(4), 65-68.
[11] 吕忠健 龚正良. Java类库中Decorator模式的应用研究. 微型电脑应用,2003.19(7), 53-54.
[12] 王巍 辛国栋. 装饰模式应用研究. 计算机工程与设计,2008.29(8), 1884-1885,1889.
[13] Quarkus官网. https://quarkus.io/