• 设计模式之(十一)代理模式(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)代理。

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

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

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

  • 相关阅读:
    实验吧(你真的会PHP吗)CTF之代码审计最终版---解析是错的 我的才是对的
    php的intval函数
    memcached 查看所有的key
    kvm 启动libvirtd时出现错误
    mysql三种binlog日志的理解
    mysql连接提示1030
    执行curl -sSL 提示curl: (35) SSL connect error
    tomcat线程数查看
    docker 1.12.3版本搭建私有仓库,上传镜像报错:server gave HTTP response to HTTPS client”
    memcached安装
  • 原文地址:https://www.cnblogs.com/pengweiqiang/p/11219066.html
Copyright © 2020-2023  润新知