摘要:本文用一个实例场景描述Gof 23设计模式中的桥梁模式,并用Quarkus框架代码给予实现,同时也给出实现代码的UML模型。
关键字:Gof 23 设计模式 桥梁模式 Quarkus
1 基础知识
1.1 标准定义
桥梁(Bridge)模式标准定义:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
1.2 分析和说明
桥梁(Bridge)模式属于结构型设计模式。它将抽象化与实现化脱耦,使得二者可以独立的变化,也就是说将他们之间的强关联变成弱关联,也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以独立的变化。
Bridge结构如图1所示。Bridge角色包括抽象化(Abstraction)角色、修正抽象化(Refine Abstraction)角色、实现化(Implementor)角色和具体实现化(Concrete Implementor)角色。
图1 -桥梁模式结构
抽象化(Abstraction)角色:Abstraction定义抽象类的接口。维护一个指向Implemcntor类型对象的指针。抽象化(Abstraction)角色可以是接口,也可以是抽象类。属于不可缺少角色。
修正抽象化(Refine Abstraction)角色:RefinedAbstraction扩充由Abstraction定义的接口 Implementor定义实现类的接口。该接口不一定要与Abstraction的接口完全一致。
实现化(Implementor)角色:lmplementor接口仅提供基本操作。这个抽象类规范具体实现化角色,规定出具体实现化角色当有的(非私有)方法和属性。实现化(Implementor)角色可以是接口,也可以是抽象类。属于不可缺少角色。
具体实现化(Concrete Implementor)角色:Concreteimplementor实现Implementor接口并定义它的具体实现。
2 应用场景举例
比如公司有几个技术部门,分别是研发部、开发部和售后服务部。这些部门都有培训和开会等工作。培训的时候,要有培训老师、培训教材、培训人员和培训教室。对于开会也是一样的,有开会的主持人、开会地点等。所以,可以把部门理解为抽象单位,研发部、开发部和售后服务部继承抽象单位并实现具体的工作。日常工作可以抽象起来,培训和开会继承日常工作,不同的部门的日常工作是不同的。其用例图如图2所示。
图2 -桥梁模式用例图
在这里可以把AbstractDepartment类理解为抽象化(Abstraction)角色。AbstractAction类是实现化(Implementor)角色。DevelopmentDep类、FinanceDep类和MarketDep理解为修正抽象化(Refine Abstraction)角色。Meeting类和Training类理解为具体实现化(Concrete Implementor)角色。其结构类图如图3所示。
图3 -桥梁模式类图
桥梁模式实现的顺序图如图4所示,实现顺序描述:① 创建一个活动对象;② 创建一个部门对象;③-④ 把活动对象赋值给部门对象;⑤ 显示部门对象的活动情况。
图4 -桥梁模式实现顺序图
活动对象可以分为会议对象和培训对象,部门对象可以是技术部门对象,财务部门对象和市场部门对象,所以两个类型可以自己内部转化,只是通过他们的抽象类或接口实现了扩充和复用。即技术部门对象可以实现会议对象和培训对象的工作。财务部门对象和市场部门对象也可以实现会议对象和培训对象的工作。使得活动和部门二者可以独立的变化。
3.Quarkus的实现程序代码
Quarkus程序实现主要包括AbstractAction抽象类文件、AbstractDepartment抽象类文件、DevelopmentDep类文件、FinanceDep类文件、MarketDep类文件、Meeting类文件和Training类文件等6个文件。其关系如图3所示。下面分别列出这6个文件的程序代码,最后列出测试代码并显示输出结果。
AbstractAction抽象类是实现化(Implementor)角色。其类程序代码清单01所示。
程序代码清单01
public abstract class AbstractAction {
public void doAction(String depart,String title){
if (depart.length()==0) System.out.println("这是部门的标准工作活动");
System.out.println("这是"+depart+"部门的标准工作活动,"+"主题是"+title);
}
}
AbstractDepartment抽象类理解为抽象化(Abstraction)角色,其程序代码清单02所示。
程序代码清单02
public abstract class AbstractDepartment {
protected AbstractAction departAction;
public void setAbstractAction(AbstractAction action){ departAction = action ;}
public void action(String title){departAction.doAction("",title); }
}
DevelopmentDep类、FinanceDep类和MarketDep类继承AbstractDepartment类,其类程序代码清单03所示。
程序代码清单03
@ApplicationScoped
public class DevelopmentDep extends AbstractDepartment{
private String departName = "开发部";
public void action(String title){
departAction.doAction(departName,title);
}
}
@ApplicationScoped
public class FinanceDep extends AbstractDepartment {
private String departName = "财务部";
public void action(String title){
departAction.doAction(departName,title);
}
}
@ApplicationScoped
public class MarketDep extends AbstractDepartment {
private String departName = "市场部";
public void action(String title){
departAction.doAction(departName,title);
}
}
Meeting类和Training类继承AbstractAction抽象类,其类程序代码清单04所示。
程序代码清单04
@ApplicationScoped
public class Meeting extends AbstractAction {
public void doAction(String depart,String title){
if (depart.length()==0) System.out.println("这是部门的会议工作活动");
System.out.println("这是"+depart+"会议工作活动,"+"主题是"+title);
}
}
@ApplicationScoped
public class Training extends AbstractAction {
public void doAction(String depart,String title){
if (depart.length()==0) System.out.println("这是部门的培训工作活动");
System.out.println("这是"+depart+"培训工作活动,"+"主题是"+title);
}
}
桥梁模式测试程序的代码清单05如下:
程序代码清单05
public class BridgeClient implements QuarkusApplication {
@ConfigProperty(name = "gof23.structuralpattern.bridge.title", defaultValue = "gof23")
String title;
@Inject Training action1;
@Inject DevelopmentDep depart1;
@Inject Meeting action2;
@Inject FinanceDep depart2;
@Inject Training action3;
@Inject MarketDep depart3;
public void scene1() {
// 场景1:针对开发部的培训工作
depart1.setAbstractAction(action1);
depart1.action("提高开发技能");
}
public void scene2() {
// 场景2:针对财务部的会议
depart2.setAbstractAction(action2);
depart2.action("检查会计制度");
}
public void scene3() {
// 场景2:针对市场部的培训
depart3.setAbstractAction(action3);
depart3.action("沟通技巧");
}
@Override
public int run(String... args) {
scene1();
scene2();
scene3();
return 0;
}
public static void main(String... args) {
Quarkus.run(BridgeClient.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\bridge”目录中。
同时也可以从gitee上clone预先准备好的示例代码,命令如下:
git clone https://gitee.com/rengang66/quarkus-sample-gof23.git
5 扩展和说明
JDK中的AWT就是采用的桥梁模式实现。
Component是提供给开发人员对窗体界面系统的抽象,代表图形用户界面中的一个控件,对于事件响应的处理,在Component类中有ComponentEvent属性。但是,在具体实现中,针对不同的Component类型,有着不同Event事件响应。例如,如果你使用AWT创建了一个Window类的实例,那么在程序运行时会创建一个窗口的实例,而由窗口实例会产生WindowEvent响应。不同的组件,有不同的事件响应实现。所以,作为Component有自己的一套继承体系,而Event事件响应也有对应的继承体系。而Component通过关联Event把这两者结合起来,形成这种一一映射关系。其实现结构见图5所示。
图5 JDK中Component和ComponentEvent桥梁类结构图
实际上,从设计的角度来看,这是一个抽象和实现分离的过程。Component和ComponentEvent是抽象,Container和ContainerEvent是具体实现,抽象和实现各自成为一个对象体系,它们由一个桥连接起来,可以各自发展各自的对象层次,而不必顾虑另一方面。这就是Bridge模式所提供的思想。
参考文献
[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] 马维达. ACE与GoF设计模式:ACE_Reactor与Bridge模式. 程序员,2003.(12), 69-71.
[7] 张晓怀 陈业初 寇蔚. 设计模式在设备故障红外智能诊断软件中的应用. 机电设备,2007.24(11), 29-33,13.
[8] 吴超. 设计模式在数据库浏览系统中的应用. 计算机工程与科学,2006.(z2), 148-149.
[9] 洪中. 组态软件设计中的模式应用. 微计算机信息,2007.(28), 279-281.
[10] 肖保良 宋东 赵胜. 基于模式的ATS领域框架研究. 计算机测量与控制,2007.15(9), 1144-1147.
[11] 曹恒 凌正阳 蒋知峰 王剑兰. 软件设计模式在数控系统人机界面开发中的应用. 华东理工大学学报:社会科学版,2007.33(6), 878-882.
[12] 崔仂. 几种经典设计模式组合的参考架构. 电脑知识与技术,2004.(5), 79-82.
[13] 徐倩颖 杨宗源. 面向方面编程的一种新型设计模式. 华东师范大学学报:自然科学版,2008.(1), 68-74.
[14] 肖干军 齐欢 陈文明. Bridge设计模式在光标阅读机数据采集系统的实现. 计算机与现代化,2004.(7), 110-112,114.
[15] 沈建 雷航 石浩鸿. 设计模式在光传输网管系统中的应用研究. 计算机技术与发展,2007.17(3),231-232,235.
[16] 聂颖. 设计模式在图形处理软件中的应用. 计算机应用,2004.24(B12), 189-191.
[17] Quarkus官网. https://quarkus.io/