设计模式之(十一)代理模式(Proxy)

  软件开发行业有一个观点:任务问题都可以添加一个中间层来解决。代理模式也是这个思想下的产物。

  首先看下代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。就是把类委托给另外一个类,用这个类来控制对原来那个类的访问,例如对权限的控制。来看下类图。

  代理分为静态代理和动态代理。接下来我们先看下静态代理。

静态代理

 1 //接口
 2 public interface Human {
 3     public void eat();
 4     
 5     public void  breath();
 6 }
 7 
 8 //原来的对象
 9 public class Baby implements Human {
10     public void eat(){
11         System.out.println("在吃奶");
12     }
13     
14     public void  breath(){
15         System.out.println("一刻不停的呼吸!");
16     }
17 }
18 
19 //代理类
20 public class Mom implements Human{
21     private Human human;
22     public Mom(){
23         this.human = new Baby();
24     }
25     
26     public void eat(){
27         System.out.println("喂婴儿吃奶!");
28         human.eat();
29     }
30     
31     public void breath(){
32         human.breath();
33     }
34 }
35 
36 public class Client {
37     public static void main(String[] args) {
38         Human hm = new Mom();
39         hm.eat();
40         hm.breath();
41     }
42 }
43 
44 -------------------------------------------------------------------------
45 喂婴儿吃奶!
46 喜欢吃奶
47 一刻不停的呼吸!

动态代理

   动态代理的例子是利用了上面的例子中的 human 接口和 Baby 类。

//动态代理
public class ProxyMom implements InvocationHandler {

    private Human human = null;
    
    public Human getProxyInterface(Human human1){
        this.human = human1;
        Human hm = (Human)Proxy.newProxyInstance(human.getClass().getClassLoader(), human.getClass().getInterfaces(), this);
        return hm;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        // TODO Auto-generated method stub
         
        Object methodObj = null;
        System.out.println("喂婴儿吃奶!");
        methodObj = method.invoke(human, args);
        
        return methodObj;
    }
    
}

public class Client {
    public static void main(String[] args) {
        ProxyMom pm = new ProxyMom();
        Human baby= pm.getProxyInterface(new Baby());
        baby.eat();
        baby.breath();
        
    }
}
-------------------------------------------------------------------------
喂婴儿吃奶!
在吃奶
喂婴儿吃奶!
一刻不停的呼吸!

  1、java 里面动态代理需要实现 InvocationHandler 接口。

  2、然后重写 invoke 方法。参数第一个是:代理类对象。第二个是:需要代理的方法、第三个是方法的参数。另外 invoke 是自动被调样的。不需要使用者显示调用。

      通过例子我们看出来了,如果是静态代理的话,代理类和原生类都是一对一的。原生类有多少方法,那么代理类基本也需要有相应的方法来代理,这样代理类总是要跟着原生来来变化。当原生类有很多方法的时候,代理类也需要很多方法,非常的不灵活。而动态代理通过 Proxy、InvocationHandler 和 方法 invoke 就结局了这个问题。因为 invoke 能对所以的方法进行统一处理。方便灵活。

  java 的动态代理只能代理接口,而如果想要代理类,需要用到 cglib 类库。

代理的典型用例

        1、远程代理。2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。

  通过典型用法也看出来代理模式的本质就是控制对类的访问

代理模式和装饰模式的区别

  当然他们在实现上是极为相似的。但是代理模式强调的是对类的访问控制,而装饰模式主要是为了给类动态的增强功能。

猜你喜欢

转载自www.cnblogs.com/pengweiqiang/p/11219066.html
今日推荐