摘要:本文用一个实例场景描述Gof 23设计模式中的代理模式,并用Quarkus框架代码给予实现,同时也给出实现代码的UML模型。
关键字:Gof 23 设计模式 代理模式 Quarkus
1 基础知识
1.1 标准定义
代理(Proxy)模式标准定义:为其他对象提供一种代理以控制对这个对象的访问。
1.2 分析和说明
代理(Proxy)模式属于结构型设计模式。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入。
代理(Proxy)模式结构如图1所示,其角色包括抽象主题(Subject)角色、代理主题(Proxy)角色和真实主题(Real Subject)角色。
图1 代理模式结构
抽象主题(Subject)角色:声明了真实主题和代理主题的共同接口,这样一来在任何可以使用真实主题的地方都可以使用代理主题。该类的实现中保存一个引用使得代理可以访问实体.提供一个与实体接口相同的代理接口,这样代理就可以用来替代实体来控制对实体的存取,并可能负责创建和删除实体
代理主题(Proxy)角色:代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象;代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候都可以替代真实主体;控制对真实主题的引用,负责在需要的时候创建真实主题对象(和删除真实主题对象);代理角色通常在将客户端调用传递给真实的主题之前或者之后,都要执行某个操作,而不是单纯地将调用传递给真实主题的对象。
真实主题(Real Subject)角色:定义了代理角色所代表的真实对象,包含实体具体实现代码。
2 应用场景举例
比如公司为了拓展业务,在A省设置办事处。所有在A省的用户请求,都通过该办事处转达到公司,其中办事处就是一个代理机构。用例见图2所示。
图2 代理模式用例图
在这里可以把AbstractOrganization类理解为抽象主题(Subject)角色。Agency类是代理主题(Proxy)角色。Corporation类是真实主题(Real Subject)角色。其结构类图如图3所示。Corporation只用继承AbstractOrganization类,而Agency类一方面要继承AbstractOrganization类,同时要聚合Corporation类。
图3 代理模式类图
代理模式实现顺序图见图4,实现顺序描述:① 创建一个代理Proxy对象;② 创建一个Corporation对象。③ 客户向Proxy对象发出request请求。④ Proxy对象向Corporation对象发出request请求。⑤Corporation对象向Proxy对象返回请求的答复。⑥ Proxy对象向客户返回请求的答复。
图4 代理模式顺序图
3.Quarkus的实现程序代码
Quarkus程序实现主要包括AbstractOrganization抽象类文件,Agency类文件和Corporation类文件等3个文件。其关系如图3所示。下面分别列出这3个文件的程序代码,最后列出测试代码并显示输出结果。
AbstractOrganization类程序代码清单01所示。
程序代码清单01
public abstract class AbstractOrganization {
public void request(){};
}
Agency类程序代码清单02所示。
程序代码清单02
@ApplicationScoped
public class Agency extends AbstractOrganization {
private Corporation corporation;
public void request() {
if (corporation == null)
corporation = new Corporation();
corporation.request();
}
}
Corporation类程序代码清单03所示。
程序代码清单03
@ApplicationScoped
public class Corporation extends AbstractOrganization{
public void request(){
System.out.print("这是公司的答复。");
System.out.println();
}
}
代理模式测试程序的代码清单04如下:
程序代码清单04
public class ProxyClient implements QuarkusApplication {
@ConfigProperty(name = "gof23.structuralpattern.proxy.title", defaultValue = "gof23")
String title;
@Inject Agency agency ;
@Override
public int run(String... args) {
System.out.println("—————" + title + "演示输出—————");
agency.request();
return 0;
}
public static void main(String... args) {
Quarkus.run(ProxyClient.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\proxy”目录中。
同时也可以从gitee上clone预先准备好的示例代码,命令如下:
git clone https://gitee.com/rengang66/quarkus-sample-gof23.git
6 扩展和说明
JDK中有专门设计实现了Proxy设计模式。只不过它叫动态代理,因为它的代理类变成了InvocationHandler了,执行的方法是invoke了,从而变得更加灵活了。
Proxy模式由 java.lang.reflect.Proxy 类、java.lang.reflect.InvocationHandler类等组成。Proxy类拥有一个 protected 的 InvocationHandler 类型的成员变量。它只能代理 Interface。
java.lang.reflect.Proxy提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。动态代理类是一个实现在创建类时在运行时指定的接口列表的类。
InvocationHandler是代理实例的调用处理程序实现的接口,也可以说是代理类实现的一个接口。。
代理实例是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序对象,它可以实现接口 InvocationHandler。通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的 Invoke方法,并传递代理实例、识别调用方法的 java.lang.reflect.Method 对象以及包含参数的 Object 类型的数组。调用处理程序以适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。
参考文献
[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] 张婧 朱晓民 廖建新. 基于设计模式对WV网关业务逻辑处理模块的重构. 计算机系统应用,2008.(10),
[7] 板桥里人. Jive和设计模式. 程序员,2003.(6), 58-60.
[8] 谭炎 潘久辉. 开放源代码项目Jive的体系结构与设计模式. 科学技术与工程,2005.5(15), 1087-1090.
[9] 吴兰. 论代理模式在面向对象编程中的运用. 连云港师范高等专科学校学报,2008.(2), 95-99.
[10] 朱彬 王娜 王安保. 业务代理模式在Struts和Hibernate框架中的应用. 上海第二工业大学学报,2007.24(4), 276-280.
[11] 周营烽 魏宝尉 范战新. Proxy思想在代码集成中的应用. 计算机工程,2004.30(13), 56-57,86.
[12] 刘勇平 郝志峰 田翔 冯应昌. 基于代理设计模式的银电联网电费缴纳系统. 计算机工程,2007.33(8), 259-261.
[13] 黄素英 王周敬. 面向对象框架在信息系统开发中的应用. 合肥工业大学学报:自然科学版,2003.(z1), 896-898.
[14] 叶建平. 设计模式在游乐设施检测管理信息系统中的应用. 微计算机信息,2005.21(12X), 213-214,77.
[15] 曾蔚 陈维斌. 设计模式在新生报到系统中的应用与实现. 计算机技术与发展,2007.17(7), 178-182.
[16] 黄观波 杜江洪 吴素浓. 设计模式在基于J2EE的分布式ERP系统中的应用. 煤矿现代化,2005.(1), 37-39.
[17] 汪永好. 设计模式在工作流管理系统实现中的应用. 计算机工程与设计,2006.27(6), 1096-1097,1100.
[18] 韩鹏 李成忠. 设计模式及其在J2ME中的应用. 成都信息工程学院学报,2004.19(3), 332-335.
[19] 聂颖. 设计模式在图形处理软件中的应用. 计算机应用,2004.24(B12), 189-191.
[20] Quarkus官网. https://quarkus.io/