代理 模式
Posted wonkju
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代理 模式相关的知识,希望对你有一定的参考价值。
概述:
代理模式:为另一个对象提供一个替身(或占位符),以控制对该对象的访问;
使用代理模式创建代理对象,让代理对象控制某对象的访问,被代理的对象可以是远程(或创建开销大、需要安全控制的)对象。
要点:
- 代理角色内部含有对真实角色的引用:从而可以在任何时候操作真实角色对象;
- 代理角色与真实角色实现同一接口:以便可以在任何时候都可以替代真实角色,负责在需要的时候创建(删除)真实角色对象。
- 代理角色通常在将客户端调用传递给真实主题之前(或之后),都要执行某个操作(如检验参数),而非单纯将调用传递给真实角色对象。
一、uml类图
二、(静态)代理 模式的实现
1,主题角色
package static_proxy; //主题角色(抽象) public interface IBuyCar { public void buyCar(); }
2,目标角色
View Code
3,代理角色
1 package static_proxy; 2 3 public class BuyCarProxy implements IBuyCar{ 4 private Customer customer;//接收买车客户 5 6 public BuyCarProxy(Customer customer){ 7 this.customer=customer;//接收买车客户 8 } 9 10 @Override 11 public void buyCar() {//实现为客户买车 12 customer.buyCar(); 13 } 14 15 }
4,测试
1 package static_proxy; 2 3 public class Main { 4 public static void main(String[] args) { 5 Customer customer = new Customer(); 6 customer.setCash(120000); 7 8 BuyCarProxy buyCarProxy = new BuyCarProxy(customer); 9 buyCarProxy.buyCar(); 10 } 11 }
三、(动态)代理 模式的实现(通过 jdk)
JDK提供的动态代理需要实现InvocationHandler
接口的invoke
方法(此方法为整个代理的入口)。
方法签名:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
第一个参数proxy:代理对象
第二个参数目method:目标方法
第三个参数args:目标方法的参数
问题:若使用(静态)代理,则当目标接口需要增加新的方法时,则对应的代理类也需要进行相应的改动,维护工程比较大。故需要(动态)代理
(静态-》动态)目标接口以及目标实现不需要改变,但BuyCarProxy(静态代理类)修改为实现InvocationHandler的处理类:
1,静态代理类 修改 为
1 package dynamic_proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 public class ProxyHandler implements InvocationHandler{ 7 Object target; 8 9 public ProxyHandler(Object target) { 10 this.target=target; 11 } 12 //验证参数(代理对象处理目标对象前) 13 public void before(String param){ 14 System.out.println("参数检验:" + param); 15 } 16 @Override 17 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 18 this.before(null); 19 20 return method.invoke(this.target, args); 21 } 22 23 24 }
2,测试类(即使增加实现的方法,也不用修改代理)
1 package dynamic_proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Proxy; 5 6 public class Main { 7 public static void main(String[] args) { 8 //我们要代理的真实对象 9 Customer customer = new Customer(); 10 //我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的 11 InvocationHandler handler = new ProxyHandler(customer); 12 13 /* 14 * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数 15 * 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象 16 * 第二个参数customer.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了 17 * 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上 18 */ 19 IBuyCar buyCar = (IBuyCar) Proxy.newProxyInstance(handler.getClass().getClassLoader(), customer.getClass().getInterfaces(), handler); 20 buyCar.search(); 21 buyCar.buyCar(); 22 } 23 }
以上是关于代理 模式的主要内容,如果未能解决你的问题,请参考以下文章