• 设计模式-动态代理


    通过代理模式 ,代理类可以在被代理类的基础上做前置和后置的操作。---- 代理类就好比 房产中介或者代购,买方只要通过中介,就可以购买到房子或者想要的东西。中介提供 售前和售后的服务。

    静态代理

    通过封装被代理的类的方法,在方法前后增加增强的代码。缺点是,每次扩展一个方法 ,都需要修改代理类。

    例如

    public class Lison {
        
        AaFactory aaFactory = new AaFactory();
        BbFactory bbFactory = new BbFactory();
        
        public void getManToolsFactroy(){
            System.out.println("我是getManToolsFactroy方法前置增强");
            aaFactory.saleManTools(20);
            System.out.println("我是getManToolsFactroy方法后置增强");
        }
        public void getWomanToolsFactroy(){
            System.out.println("我是getWomanToolsFactroy方法前置增强");
            bbFactory.saleWomanTools(20);
            System.out.println("我是getWomanToolsFactroy方法后置增强");
        }
      //...... }

     又或者

    public class Lison2 implements ManToolsFactory,WomanToolsFactory {
        
        public ManToolsFactory factory = new AaFactory();
        public WomanToolsFactory wFactory  = new BbFactory();
        
        public Lison2() {
        }
        
        @Override
        public void saleManTools(int size) {
            System.out.println("我是saleManTools方法前置增强");
            factory.saleManTools(20);
            System.out.println("我是saleManTools方法后置增强");
        }
        @Override
        public void saleWomanTools(int size) {
            // TODO Auto-generated method stub
            System.out.println("我是saleWomanTools方法前置增强");
            wFactory.saleWomanTools(20);
            System.out.println("我是saleWomanTools方法后置增强");
        }
    }

    这两种方法区别不大,一个是通过自己新增方法,实现代理其他类。一个是通过实现接口的方法

    动态代理

    符合开闭原则,只要扩展被代理类的接口和实现类,然后直接 动态 提供代理服务

    这是代理类

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class LisonCompany1 implements InvocationHandler {
        
        //被代理的对象
        Object factory;
        public Object getFactory() {
            return factory;
        }
        public void setFactory(Object factory) {
            this.factory = factory;
        }
        //获取动态代理对象实例
        //,调度员工
        //通过Proxy 获取动态代理的对象
        //第一个参数,类加载器。因为factory和 LisonCompany 是在同一个类里面,所以就用factory.getClass().getClassLoader()
        //第二个参数,指定的接口
        public Object getProxyInstance(){
            return Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), this);
        }
        
        public LisonCompany1() {
        }
        public LisonCompany1( Object factory) {
            this.factory = factory;
        }
        @Override
        //通过代理对象,将方法争强
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("前置增强,售前服务,市场调研");
            Object ret = method.invoke(factory, args);
            System.out.println("后置增强,精美包装");
            return ret;
        }
    }

     这是被代理的接口:

    public interface ManToolsFactory {
        
        void saleManTools(int size);
    
    }

     这是被代理的实现类:

    public class AaFactory implements ManToolsFactory {
    
        @Override
        public void saleManTools(int size) {
            System.out.println("定制size="+size+"女模特");
        }
    
    }

     这是测试的main方法

    import test.designpatterns.proxy.dynamic.LisonCompany1;
    import test.designpatterns.proxy.staticc.AaFactory;
    import test.designpatterns.proxy.staticc.BbFactory;
    import test.designpatterns.proxy.staticc.Lison;
    import test.designpatterns.proxy.staticc.Lison2;
    import test.designpatterns.proxy.staticc.ManToolsFactory;
    import test.designpatterns.proxy.staticc.WomanToolsFactory;
    import test.designpatterns.proxy.util.ProxyUtil;
    
    public class Client  {
        public static void main(String[] args) {
            
            System.out.println("-----------------------------静态代理1");
            //每次增加需求,不仅需要增加某工厂类,例如化妆品工厂类,Lison对象需要做修改,违背了 面向对象设计原则(单一职责原则),和下面静态代理2一样的问题
            //静态代理不符合开闭原则
            Lison lison = new Lison();
            lison.getManToolsFactroy();
            lison.getWomanToolsFactroy();
            System.out.println("-----------------------------静态代理2");
            Lison2 lison2 = new Lison2();
            lison2.saleManTools(100);
            lison2.saleWomanTools(200);
            
            System.out.println("-----------------------------动态代理");
            ManToolsFactory aFactory = new AaFactory();
            WomanToolsFactory bFactory = new BbFactory();
            //LisonCompany对象不用修改,直接增加Factory类 用动态代理Proxy就可以或者对应的方法
            LisonCompany1 lisonCompany = new LisonCompany1();
            lisonCompany.setFactory(aFactory);
            LisonCompany1 lisonCompany2 = new LisonCompany1();
            lisonCompany2.setFactory(bFactory);
            //委派一号员工
            ManToolsFactory lison0 = (ManToolsFactory) lisonCompany.getProxyInstance();
            WomanToolsFactory lison1 = (WomanToolsFactory) lisonCompany2.getProxyInstance();
            lison0.saleManTools(60);
            lison1.saleWomanTools(40);
            
            ProxyUtil.generateClassFile(aFactory.getClass(), lison0.getClass().getSimpleName());
            
            
        }
    
    }

    控制台打印的输出:

    -----------------------------静态代理1
    我是getManToolsFactroy方法前置增强
    定制size=20女模特
    我是getManToolsFactroy方法后置增强
    我是getWomanToolsFactroy方法前置增强
    定制size=20男模特
    我是getWomanToolsFactroy方法后置增强
    -----------------------------静态代理2
    我是saleManTools方法前置增强
    定制size=20女模特
    我是saleManTools方法后置增强
    我是saleWomanTools方法前置增强
    定制size=20男模特
    我是saleWomanTools方法后置增强
    -----------------------------动态代理
    前置增强,售前服务,市场调研
    定制size=60女模特
    后置增强,精美包装
    前置增强,售前服务,市场调研
    定制size=40男模特
    后置增强,精美包装
    
  • 相关阅读:
    什么是web标准
    Axure 快捷方式
    asp.net mvc4中model与Model的区别
    Git 操作常用命令
    ASP.NET MVC 中@html.ActionLink的几种参数格式
    Datagridview控件实现分页功能
    winform 拖动无边框窗体(调用Windows API)
    利用C#轻松创建不规则窗体
    Linq to sql 操作
    第一篇博客,写些学习感想
  • 原文地址:https://www.cnblogs.com/jkwll/p/11712515.html
Copyright © 2020-2023  润新知