美文网首页
Java 设计模型--代理模式

Java 设计模型--代理模式

作者: superHang | 来源:发表于2020-04-13 18:03 被阅读0次

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

    学习了下面两篇文章
    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方法。
    ``
    
    
    
    

    相关文章

      网友评论

          本文标题:Java 设计模型--代理模式

          本文链接:https://www.haomeiwen.com/subject/ncdnmhtx.html