设计模式之代理设计模式

381 阅读4分钟

原文首发于微信公众号:jzman-blog,欢迎关注交流!

今天来看一下什么是代理设计模式,顾名思义,代理就是通过中介代替某人做某一件事,对应到我们的程序中就是通过代理对象来控制某个具体对象某个方法的访问,在该方法之前和之后可以做一些额外处理。

  1. 概念理解
  2. 静态代理
  3. 动态代理

概念理解

  • 抽象角色:用于定义真实角色和代理角色共有的方法。
  • 真实角色:真实角色要实现的具体业务逻辑以供代理角色调用。
  • 代理角色:用于代理真实角色,可在真实角色具体逻辑前后进行额外处理。

那么代理的意义在于,当需要具体的业务逻辑时才调用真实角色的具体业务方法,即与真实角色具体业务逻辑无关的处理都放在代理类中的处理。

静态代理

先来看一下静态代理的代码实现,定义抽象角色声明共用的业务逻辑,具体如下:

/**
 * 抽象角色
 * @author jzman
 */
public interface IBusiness {
	/**
	 * 购物
	 */
	void buy();
}

然后,创建真实角色并完成具体的业务逻辑,具体如下:

/**
 * 真实角色
 * @author jzman
 */
public class RealRole implements IBusiness{
	@Override
	public void buy() {
		System.out.println("我要买东西");
	}
}

然后,创建代理角色,在进行具体业务逻辑的时候必须调用真实角色的业务逻辑方法,具体如下:

/**
 * 代理角色
 * @author jzman
 */
public class ProxyRole implements IBusiness{
	
	private IBusiness mRealRole;
	
	public ProxyRole(IBusiness realRole) {
		this.mRealRole = realRole;
	}

	@Override
	public void buy() {
		//购买之前的额外评估
		System.out.println("购买之前的额外评估...");
		//具体的业务逻辑
		mRealRole.buy();
		//购买之后的满意度调查
		System.out.println("购买之后的满意度调查...");
	}
}

最后,使用刚才创建的相关静态代理类,具体如下:

/**
 * 测试静态代理
 * @author jzman
 */
public class StaticClient {
	public static void main(String[] args) {
		//创建真实角色
		IBusiness realRole = new RealRole();
		//创建代理角色
		IBusiness proxyRole = new ProxyRole(realRole);
		//代购帮你买东西
		proxyRole.buy();
	}
}

测试效果如下:

购买之前的额外评估...
我要买东西
购买之后的满意度调查...

这个案例中,代购不仅帮我们买到了东西,而且在购买行为发生之前和之后做了额外的处理,是不是比较非常灵活呢。

动态代理

上面了解了静态代理,那么动态代理与静态代理有什么区别呢,实际上静态代理和动态代理主要区别是静态代理需要自己生成代理类,而动态代理是在代码运行过程中自动生成代理类,那么动态代理如下实现呢,先来看一看 Java JDK 自带的实现动态代理的关键的两个类或接口,具体如下:

//用于动态生成代理类及其对象
java.lang.reflect.Proxy
//代理角色的调用处理程序需要实现的接口
//用于约束调用者的实现,抽象角色调用方法的时候会被该接口的invoke方法调用
java.lang.reflect.InvocationHandler

下面就来实现一下 Java JDK 自带的动态代理,首先抽象角色和真实角色和上文中静态代理的一样,这里就不在赘述,创建一个代理角色的调用处理程序如下:

/**
 * 代理角色的调用处理程序
 * @author jzman
 */
public class BusinessHandler implements InvocationHandler{

	private IBusiness mRealRole;
	
	public BusinessHandler(IBusiness mRealRole) {
		super();
		this.mRealRole = mRealRole;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//购买之前的额外评估
		System.out.println("购买之前的额外评估...");
		
		//真实角色具体的业务逻辑
		method.invoke(mRealRole, args);
		
		//购买之后的满意度调查
		System.out.println("购买之后的满意度调查...");
		
		return null;
	}
}

使用 Proxy 的静态方法 newProxyInstance() 来生成代理对象,具体如下:

/**
 * 测试JDK自带的动态代理
 * @author jzman
 *
 */
public class DynamicProxyClient {
	public static void main(String[] args) {
		//创建真实角色
		IBusiness mRealRole = new RealRole();
		
		//创建处理器接口
		InvocationHandler handler = new BusinessHandler(mRealRole);
		/**
		 * 获取代理角色对应的代理对象
		 * newProxyInstance参数(类加载器,自动生成的代理类实现的接口,代理对象的调用处理程序)
		 */
		IBusiness proxy = (IBusiness) Proxy.newProxyInstance(handler.getClass().getClassLoader(), mRealRole.getClass().getInterfaces(), handler);
		
		//代理角色帮你买东西
		proxy.buy();
	}
}

上述代码的执行结果如下:

购买之前的额外评估...
我要买东西
购买之后的满意度调查...

学习静态代理有助于对动态代理的学习,两者主要的区别就是动态代理不需要写代理类,其相应的代理类会在代码运行期间动态生成,当然生成的代理类也实现了抽象角色对应的接口,同时创建个代理角色的调用者处理程序(InvocationHandler)也会接管具体的业务逻辑。关于静态代理和动态代理就到此为止。可以选择关注个人微信公众号:躬行之 获取最新更新,一起交流学习!

1.png