Java 设计模型--代理模式

2020-04-13  本文已影响0人  superHang

代理模式就是:当前对象不愿意干的,没法干的东西委托给别的对象来做,我只要做好本分的东西就好了!

学习了下面两篇文章
https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247484222&idx=1&sn=5191aca33f7b331adaef11c5e07df468&chksm=ebd7423fdca0cb29cdc59b4c79afcda9a44b9206806d2212a1b807c9f5879674934c37c250a1&scene=21#wechat_redirect

https://www.cnblogs.com/doucheyard/p/5737366.html

静态代理

上面的文章挺好的,我就直接复用例子就好了

用小婴儿说明,小baby只会吃和睡,拉了粑粑,但是自己不会擦屁股呀,然后他妈妈只能找个保姆,保姆就是被他妈妈代理来照顾婴儿

public class Baby implements Human {
    
  @Override
    public void eat(){
        System.out.println("小婴儿只能吃奶....");
    }

    @Override
    public void shit() {
        System.out.println("小婴儿拉粑粑....");
    }

//保姆类---一个代理类
public class BabySitter implements Human {
  private Baby baby;

    //构造函数
    public BabySitter(Baby baby){
        this.baby=baby;
    }

    public void wipeShit(){
        System.out.println("帮助婴儿擦屁屁。。。。");
    }

    @Override
    public void eat() {

    }
    @Override
    public void shit() {
      baby.shit();
      //帮助婴儿擦屁屁
      wipeShit();
    }
}

将婴儿和保姆关联起来,并在保姆类中添加帮助擦屁屁的方法

public class BabySitter implements Human {
     private Baby baby;

    //构造函数
    public BabySitter(Baby baby){
        this.baby=baby;
    }
    
    @Override
    public void shit() {
      //拉粑粑
      baby.shit();
     //擦屁屁
      wipeShit();
    }

    
    public void wipeShit(){
        System.out.println("帮助婴儿擦屁屁。。。。");
    }

妈妈调用

public class Mom {

    public static  void main(String [] args){
        Human human = new BabySitter(new Baby());
        human.shit();
    }
}
image.png

装饰模式主要是强调对类中代码的拓展,而代理模式则偏向于委托类的访问限制。两者都一样拥有抽象角色(接口)、真实角色(委托类)、代理类 。

\color{red}{如静态代理的内容所描述的,静态代理受限于接口的实现。动态代理就是通过使用反射,动态地获取抽象接口的类型,从而获取相关特性进行代理}

动态代理

实现InvocationHandler

public class HealthHandle implements InvocationHandler {

    private Object proxyTarget;
    public Object getProxyInstance(Object target){
        this.proxyTarget = target;
//Proxy.newProxyInstance(Clas loader, Class<?>[] interfaces, InvocationHandler h)
        return Proxy.newProxyInstance(proxyTarget.getClass().getClassLoader(), proxyTarget.getClass().getInterfaces(), this);
    }

   @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object methodObject = null;
        if(method.getName().equals("shit")){
            methodObject = method.invoke(proxyTarget, args);
            System.out.println("帮助婴儿擦屁屁.......");
        }else if(method.getName().equals("eat")){
            System.out.println("帮助婴儿饭前洗手.......");
            methodObject = method.invoke(proxyTarget, args);
        }
        return methodObject;
    }

妈妈类调用,动态代理了两个动作,在婴儿拉粑粑后,帮他洗屁屁,在他吃饭前,帮他洗手,不再用保姆类了

    public static  void main(String [] args){
        HealthHandle h = new HealthHandle();
        Human human = (Human) h.getProxyInstance(new Baby());
        human.shit();
        human.eat();
    }

image.png

使用动态代理:
1.必须实现InvocationHandler接口,订立一个契约标识该类为一个动态代理执行类
2.InvocationHandler接口内有一实现方法签名如下: public Object invoke(Object proxy, Method method, Object[] args) 。使用时需要重写这个方法
3.获取代理类,需要使用 Proxy.newProxyInstance(Clas loader, Class<?>[] interfaces, InvocationHandler h) 这个方法去获取Proxy对象(Proxy类类型的实例,非BABY类类型实例)。
就是不能写成 :
Baby baby = (Baby) h.getProxyInstance(new Baby());
要写他的抽象类

 //Clas loader : 类的加载器

//Class<?>[] interfaces : 委托类实现的接口,保证代理类返回的是同一个实现接口下的类型,保持代理类与抽象角色行为的一致
  //invocationHandler, 该类最重要的一环。一个设计模式:策略模式.即告诉代理类,代理类遇到某个委托类的方法时该调用哪个类下的invoke方法。
  Proxy.newProxyInstance(Class loader, Class<?>[] interfaces, InvocationHandler h) 
     //第一个参数为Proxy类类型实例,如匿名的$proxy实例
  //第二个参数为委托类的方法对象
    //第三个参数为委托类的方法参数
  //返回类型为委托类某个方法的执行结果
   public Object invoke(Object proxy, Method method, Object[] args)
  
   总的来说这个方法就是动态获取委托类里面的方法,在调用委托类的方法时在这个方法内进行拓展。 通过上面的Proxy.newProxyInstance方法,告诉底层代码,该去哪个类里面执行invoke方法。
``



上一篇下一篇

猜你喜欢

热点阅读