zoukankan      html  css  js  c++  java
  • java代理模式

    java代理模式

    首先看一张类图,感觉这幅图的描述是比较准确的。subject是一个接口,底下代理类和被代理类实现了这个接口,而被代理类和代理类是关联关系(我理解为代理类包含了一个被代理类的实体)。

    代理模式感觉就是把被代理类的装进代理类中,重写被代理类的方法,由于他们共同都实现了一个接口,在代理类中调用方法,实际上就是访问重新封装的方法了。这样做的好处是,一个代理类可以服务多个不同的类,重新封装他们的方法,当然这些类都必须实现同一个接口。

    下面的例子我们使用顾客-点餐例子来讲述代理模式。

    在点餐的时候,无论是商人、学生、小朋友都要通过服务员来点餐,此时服务员可以当成是一个代理。而不同种类的顾客可以当成是被代理的人。

    代码如下:

    Customer.java

    package reflection.normalproxy;
    
    public interface Customer {
        public void orderDish();
    }

    WaiterProxy.java

    package reflection.normalproxy;
    
    public class WaiterProxy implements Customer {
    
        Customer customer;
        public WaiterProxy(Customer customer){
            this.customer=customer;
        }
        @Override
        public void orderDish() {
            // TODO Auto-generated method stub
            System.out.println("order before");
            customer.orderDish();
            System.out.println("order after");
            
        }
    
    }

     CustomerImpl.java

    package reflection.normalproxy;
    
    public class CustomerImpl implements Customer {
    
        @Override
        public void orderDish() {
            // TODO Auto-generated method stub
            System.out.println("custom order");
            
        }
        public static void main(String args[]){
            Customer c=new CustomerImpl();
            Customer p=new WaiterProxy(c);
            p.orderDish();
        }
    }

     我们把主函数写在了最后一个类里面

    输出:

    order before
    custom order
    order after

    上面的例子有不方便的地方,就是代理类必须实现某个接口,于是我们可以使用java反射机制的代理类。

    Customer.java 还是一样

    package reflection.normalproxy;
    
    public interface Customer {
        public void orderDish();
    }

    WaiterHandler.java

    package reflection.proxyclass;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class WaiterHandler implements InvocationHandler {
    
        Object customer;
        public WaiterHandler(Object customer){
            this.customer=customer;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // TODO Auto-generated method stub
            System.out.println("order before");
            Object result=method.invoke(customer, args);
            System.out.println("order after");
            
            return result;
        }
    }

    这个类要实现InvocationHandler接口,跟之前的WaiterProxy类类似,里面提供一个代理方法,只不过这个代理方法是有后面的代理类调用的。

    构造函数里面传入被代理的类customer,它可以是非基础类型的Object。

    method.invoke()的参数制定了需要代理的类也就是customer以及调用方法时候的参数args,返回值result对应调用代理类调用这个方法的返回结果。由于这个类没有实现接口,有一个问题,那么怎么知道它要调用什么方法呢?如下。

    CustomImpl.java

    package reflection.proxyclass;
    
    import java.lang.reflect.Proxy;
    
    public class CustomerImpl implements Customer {
    
        @Override
        public void orderDish() {
            // TODO Auto-generated method stub
            System.out.println("custom order");
            
        }
        public static void main(String args[]){
            CustomerImpl c=new CustomerImpl();
            WaiterHandler h=new WaiterHandler(c);
            
            Customer ci=(Customer)Proxy.newProxyInstance(c.getClass().getClassLoader(), c.getClass().getInterfaces(), h);
            ci.orderDish();
        }
    }
    我们把需要代理的类以及handler传入Proxy.newProxyInstance(),这样利用java反射机制,Proxy会获得需要调用的接口的方法。在我们调用这些接口方法的时候,Proxy会调用invoke()方法进行代理。
  • 相关阅读:
    Altium Designer 16 问题解决
    IAR FOR AVR 仿真过程中出现全局变量值不断随意变化的问题
    linux '--stdin'错误 -批量修改密码
    EmWin 字体相关函数
    EmWin 文本显示函数
    Win10下 usart驱动PL2303无法安装的问题
    EmWin 接触---基础函数
    Linux 下 Samba 服务器搭建
    MPLAB X IDE V4.15 创建工程,编译,问题处理
    EF Core MVC
  • 原文地址:https://www.cnblogs.com/actionscr/p/4866261.html
Copyright © 2011-2022 走看看