zoukankan      html  css  js  c++  java
  • JDK动态代理

      案例:我要定制一双鞋,势必要自己四处奔波找厂商,要对鞋的大小,款式,材料等繁琐的小事的操心,然后跟鞋厂对接好完之后,我又要过去验货,最后才能带回家。这样买鞋所花的时间成本肯定是不划算的,要是有一个提供代理服务的中间人就好了。

    编写代理模式有3点必须遵从:

      1.代理对象必须包含真实的对象

      2.必须和真实对象实现同一个接口

      3.必须提供更多的功能 (代理的目的不就是为了提供更多的服务吗)

    案例编写:

      一:创建被代理对象

    /**
     * 1. 接口, 描述了服务提供者的行为
     */
    public interface A_ShoesFactory {
        
        // 订制鞋子。
        void saleShoes(int size);
    }

      二:创建这个接口的具体实现

    /**
     * 1. 真正提供服务的类,销售鞋子的厂商。
     */
    public class A_ShoesFactoryImpl implements A_ShoesFactory{
    
        @Override
        public void saleShoes(int size) {
            System.out.println("为你量身定制了一双: "+size+" 码的鞋子!");
        }
    }

      三:创建代理对象

    /**
     * 【静态代理类】
     *  代理对象,
     *         必须包含真实的对象,
     *         必须和真实对象实现同一个接口,
     *         并且提供更多的功能。
     */
    public class Service_Static implements A_ShoesFactory{
    
        //被包含的真实对象
        private A_ShoesFactory factory;
        
        public Service_Static(A_ShoesFactory factory) {
            super();
            this.factory = factory;
        }
        
        @Override
        public void saleShoes(int size) {
            doSomeThingBeFore();//前置增强
            factory.saleShoes(size);
            doSomeThingEnd();//后置增强
        }
        
        //售前任务
        private void doSomeThingBeFore(){
            System.out.println("根据您的需求,进行市场调研和产品分析!");
        }
        
        //售后任务
        private void doSomeThingEnd(){
            System.out.println("精美包装,快递一条龙服务。终身保修!");
        }
    
    }

    四: 创建客户端(测试)

    public class Client {
    
       //【静态代理测试】
        public static void main(String[] args) {
            //1. 从前有一个售卖鞋子的厂商
            A_ShoesFactory factory = new A_ShoesFactoryImpl();
            //2. 代购商来帮你代购这个产品
            Service_Static wl = new Service_Static(factory);
            //3. 根据你的需求,定制了一双40码的AJ运动鞋。
            wl.saleShoes(40);
        }    
    }
    
    ===================================
    【控制台输出结果】
    
    根据您的需求,进行市场调研和产品分析!
    为你量身定制了一双: 40 码的鞋子!
    精美包装,快递一条龙服务。终身保修!

    看完上面的场景我们对代理模式有了个大概地认识:

      优点:1、职责清晰。 2、高扩展性。 3、 对服务者和消费者的关系解耦,保护了服务者对象,解决了直接访问目标的不必要复杂性。

      缺点:需要在客户端和真实主题之间增加了代理对象,实现起来会稍微有些麻烦。

    这仅仅只是一个静态代理模式。如果此时代理商要扩展业务,不仅仅代理鞋子还要代理衣服,那怎么办?

    如果要代理衣服,那么:

      1. 按照上面的一、二步,先写个衣服的接口和实现类。

      2. 代理对象再实现一个衣服,重写它里面的具体方法。

    No  No  No,这仅仅是代理2个产品,就这么麻烦,如果我要是代理几千的产品,那代理对象岂不是要实现几千个接口?其实这种情况严重的违反了设计模式中的【开闭原则】 对扩展开放,对修改关闭。我们的代理对象不应该管具体代理的是什么商品,而是不管任何商品我都应该采用同一个方法去代理。

    不多说了,继续上代码。

      一:首先按照上面的步骤,编写一个衣服的接口和实现类。

    /**
     * 1. 接口, 描述了服务提供者的行为
     */
    public interface A_ClothesFactory {
        // 订制衣服。
        void saleClothes(String size);
    }
    /**
     * 1. 真正提供服务的类,销售衣服的厂商。。
     */
    public class A_ClothesFactoryImpl implements A_ClothesFactory{
    
        @Override
        public void saleClothes(String size) {
            System.out.println("为你量身定制了一件: "+size+" 码的连衣裙!");
        }
    }

    二: 编写JDK动态代理类

    /**
     * 【JDK动态代理类】
     *    原理: 通过反射获取被代理对象的实例,将生成后的代理对象强制转换为接口。
     */
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class Servcice_dongtai implements InvocationHandler{
        //被代理的对象是个Object类型的
        private Object factory;
        
        public Object getFactory() {
            return factory;
        }
    
        public void setFactory(Object factory) {
            this.factory = factory;
        }
        
        public Object getProxyInstance(){
            // arg0被代理的真实对象       arg1被代理接口      arg2代理对象
            return Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), this);
        }
        
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            doSomeThingBeFore();//前置增强
            Object obj = method.invoke(factory, args);
            doSomeThingEnd();//后置增强
            return obj;
        }
        //售前任务
        private void doSomeThingBeFore(){
            System.out.println("根据您的需求,进行市场调研和产品分析!");
        }
        //售后任务
        private void doSomeThingEnd(){
            System.out.println("精美包装,快递一条龙服务。终身保修!");
        }
    }

    三:编写客户端 (测试)

    public class Client {
    
        
    //    【静态代理测试】
    //    public static void main(String[] args) {
    //        //1. 从前有一个售卖鞋子的厂商
    //        A_ShoesFactory factory = new A_ShoesFactoryImpl();
    //        //2. 代购商来帮你代购这个产品
    //        Service_Static wl = new Service_Static(factory);
    //        //3. 根据你的需求,定制了一双40码的AJ运动鞋。
    //        wl.saleShoes(40);
    //    }
        
        
    //    【动态代理测试】
        public static void main(String[] args) {
            A_ShoesFactory shoes = new A_ShoesFactoryImpl();
            A_ClothesFactory clothes = new A_ClothesFactoryImpl();
            
            Servcice_dongtai service = new Servcice_dongtai();
            
            service.setFactory(shoes);
            A_ShoesFactory a = (A_ShoesFactory)service.getProxyInstance();
            a.saleShoes(40);
            
            System.out.println("-------------------");
            
            service.setFactory(clothes);
            A_ClothesFactory b = (A_ClothesFactory)service.getProxyInstance();
            b.saleClothes("S");
        }
    }
    ===================================
    【控制台输出结果】

    根据您的需求,进行市场调研和产品分析!
    为你量身定制了一双: 40 码的鞋子!
    精美包装,快递一条龙服务。终身保修!
    -------------------
    根据您的需求,进行市场调研和产品分析!
    为你量身定制了一件: S 码的连衣裙!
    精美包装,快递一条龙服务。终身保修!

  • 相关阅读:
    快乐的一天从AC开始 | 20210717 | 牛客小白月赛36J
    快乐的一天从AC开始 | 20210717 | P4839
    P7295-[USACO21JAN]Paint by Letters P【平面图欧拉公式】
    泛型
    List集合
    红黑树被定义
    单例模式的双重检查锁模式为什么必须加 volatile?
    什么是 happens-before 规则?
    解决AtomicInteger 在高并发下性能问题
    什么是指令重排序?为什么要重排序?
  • 原文地址:https://www.cnblogs.com/wlwl/p/9468348.html
Copyright © 2011-2022 走看看