代理 模式

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 }
View Code

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 }
View Code

三、(动态)代理 模式的实现(通过 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 }
View Code

  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 }
View Code

 

  

以上是关于代理 模式的主要内容,如果未能解决你的问题,请参考以下文章

scrapy按顺序启动多个爬虫代码片段(python3)

用于从 cloudkit 检索单列的代码模式/片段

java代码实现设计模式之代理模式

代理模式(静态代理动态代理)代码实战(详细)

Java设计模式-代理模式之动态代理(附源代码分析)

代理模式(静态代理)