Gof23种设计模式(12)——代理模式(Proxy)

2020年8月14日10:17:33 评论 42

1 基础知识

1.1 标准定义

代理(Proxy)模式标准定义:为其他对象提供一种代理以控制对这个对象的访问。

1.2 分析和说明

代理(Proxy)模式属于结构型设计模式。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入。

代理(Proxy)模式结构如图1所示,其角色包括抽象主题(Subject)角色、代理主题(Proxy)角色和真实主题(Real Subject)角色。

Gof23种设计模式(12)——代理模式(Proxy)

图1 代理模式结构

抽象主题(Subject)角色:声明了真实主题和代理主题的共同接口,这样一来在任何可以使用真实主题的地方都可以使用代理主题。该类的实现中保存一个引用使得代理可以访问实体.提供一个与实体接口相同的代理接口,这样代理就可以用来替代实体来控制对实体的存取,并可能负责创建和删除实体

 代理主题(Proxy)角色:代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象;代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候都可以替代真实主体;控制对真实主题的引用,负责在需要的时候创建真实主题对象(和删除真实主题对象);代理角色通常在将客户端调用传递给真实的主题之前或者之后,都要执行某个操作,而不是单纯地将调用传递给真实主题的对象。

 真实主题(Real Subject)角色:定义了代理角色所代表的真实对象,包含实体具体实现代码。

2 应用场景举例

比如公司为了拓展业务,在A省设置办事处。所有在A省的用户请求,都通过该办事处转达到公司,其中办事处就是一个代理机构。用例见图2所示。

Gof23种设计模式(12)——代理模式(Proxy)

图2 代理模式用例图

在这里可以把AbstractOrganization类理解为抽象主题(Subject)角色。Agency类是代理主题(Proxy)角色。Corporation类是真实主题(Real Subject)角色。其结构类图如图3所示。Corporation只用继承AbstractOrganization类,而Agency类一方面要继承AbstractOrganization类,同时要聚合Corporation类。

Gof23种设计模式(12)——代理模式(Proxy)

图3 代理模式类图

代理模式实现顺序图见图4,实现顺序描述:
①创建一个代理Proxy对象;
②创建一个Corporation对象。
③客户向Proxy对象发出request请求。
④Proxy对象向Corporation对象发出request请求。
⑤Corporation对象向Proxy对象返回请求的答复。
⑥Proxy对象向客户返回请求的答复。

Gof23种设计模式(12)——代理模式(Proxy)

图4 代理模式顺序图

3.Java的实现程序代码

Java程序实现主要包括AbstractOrganization抽象类文件,Agency类文件和Corporation类文件等3个文件。其关系如图3所示。下面分别列出这3个文件的程序代码,最后列出测试代码并显示输出结果。

AbstractOrganization类程序代码清单01所示。

程序代码清单01

public abstract class AbstractOrganization {
    public void request(){};
}

Agency类程序代码清单02所示。

程序代码清单02

public class Agency extends AbstractOrganization {

	private Corporation corporation;

	public void request() {
		if (corporation == null) {
			corporation = new Corporation();
		}
		corporation.request();
	}
}

Corporation类程序代码清单03所示。

程序代码清单03

public class Corporation extends AbstractOrganization {

	public void request() {
		System.out.print("这是公司的答复。");
	}
}

代理模式测试程序的代码清单04如下:

程序代码清单04

public class Client {

	public static void main(String[] args) {
		Agency agency = new Agency();
		agency.request();
	}

}

代理模式测试类输出结果如下所示:

这是公司的答复。

4 扩展和说明

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 类型的数组。调用处理程序以适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。

由此可以看出,必须让 Proxy 对象拥有一个正确的 InvocationHandler 的实现。Proxy对象由 Proxy 的静态成员函数newProxyInstance 来创建,该函数的最后一个参数为InvocationHandler 类型。动态生成的代理类实现的所有接口方法都被委托给InvocationHandler 接口的 invoke 方法。

按照这种设计模式,我们的程序代码可以修改如程序代码清单07,其实现的功能是一样的。

程序代码清单07

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Agency implements InvocationHandler {

	private Organization corporation;

	public Agency(Organization organization) {
		this.corporation = organization;
	}

	public Object invoke(Object obj, Method method, Object[] args) 
			throws Throwable {
		return method.invoke(corporation, args);
	}

	public void request() {
		Object object = Proxy.newProxyInstance(corporation.getClass().getClassLoader(),
				corporation.getClass().getInterfaces(), this);
		((Organization) object).request();
	}
}
public class Corporation implements Organization {

	public Corporation() {
	}

	public void request() {
		System.out.print("这是公司的答复。");
	}
}
package design.structuralpatterns.proxy.jdk;

public interface Organization {

	public void request();

}
public class Client {

	public static void main(String[] args) {

		Organization corporation = new Corporation();
		Agency agency = new Agency(corporation);

		agency.request();
	}
}

参考链接

7种结构型模式

Gof23种设计模式(6)——适配器模式(Adapter)
Gof23种设计模式(7)——桥接模式(Bridge)
Gof23种设计模式(8)——组合模式(Composite)
Gof23种设计模式(9)——装饰器模式(Decorator)
Gof23种设计模式(10)——外观模式(Facade)
Gof23种设计模式(11)——享元模式(Flyweight)
Gof23种设计模式(12)——代理模式(Proxy)
Gof23种设计模式 —— 结构型模式总结和比较

回到总目录Gof23种设计模式(全解析)

(转载自微信公众号:架构设计模式)

素课网
  • 本文由 发表于 2020年8月14日10:17:33
  • 转载请注明:https://www.suketech.com/9275.html
设计模式:面向对象设计的六大原则 - 总结 设计模式

设计模式:面向对象设计的六大原则 – 总结

开闭原则是面向对象设计中最基础的设计原则,它指导我们如何建立稳定灵活的系统。开闭原则可能是设计模式六项原则中定义最模糊的一个了,它只告诉我们对扩展开放,对修改关闭,可是到底如何才能做到对扩展开放,对修...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: