• 设计模式---代理模式


    代理模式分为静态代理和动态代理,静态代理比较简单,动态代理要用到反射机制

    静态代理的例子:

    日常生活中,想要联系明星出演节目,往往不是通过直接联系明星,而是联系明星的经纪人,也就是代理

    UML图如下

    不管是明星(SuperStar)还是经纪人(Broker)都实现Star接口,通过操作接口来和经纪人对接

    Star接口代码

    package cn.designmodel.proxy.staticProxy;
    
    /**
     * 抽象角色,提供代理角色和真实角色对外公共方法
     */
    public interface Star {
    
        void perform();
    }

    SuperStar代码

    package cn.designmodel.proxy.staticProxy;
    
    public class SuperStar implements Star {
    
        @Override
        public void perform() {
            System.out.println("明星表演节目");
        }
    
    }

    Broker代码

    package cn.designmodel.proxy.staticProxy;
    
    public class Broker implements Star {
    
        private Star superStar;
        
        public Broker(Star s) {
            this.superStar = s;
        }
        
        @Override
        public void perform() {
            superStar.perform();
        }
    
    }

    最后是测试程序代码

    package cn.designmodel.proxy.staticProxy;
    
    public class TestStaticProxy {
    
        public static void main(String[] args) {
            Star zjy = new SuperStar();
            Star jjr = new Broker(zjy);
            
            jjr.perform();
        }
    }

    运行结果

    明星表演节目

    可以看出,通过经纪人(jjr)表演,实现明星(zjy)的表演,这就是静态代理模式

    动态代理的例子:

    比如有个业务A和业务B,不管执行哪个业务,在执行前和执行完都需要有个记录,很像Spring里的切面一样。

    业务接口代码

    public interface AbstractSubject
    {
        public void request();
    }

    业务A和业务B代码

    public class RealSubjectA implements AbstractSubject
    {    
        public void request()
        {
            System.out.println("真实主题类A!");
        }
    }
    
    
    public class RealSubjectB implements AbstractSubject
    {    
        public void request()
        {
            System.out.println("真实主题类B!");
        }
    }

    动态代理类

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class DynamicProxy implements InvocationHandler
    {
        private Object obj;
        
        public DynamicProxy(){}
        
        public DynamicProxy(Object obj)
        {
               this.obj=obj;
           }
           
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
        {
            preRequest();
            method.invoke(obj, args);
            postRequest();
            return null;
        }
    
        public void preRequest(){
        System.out.println("调用之前!");
        }
    
        public void postRequest(){
        System.out.println("调用之后!");
        }
    
    }

    最后是测试代码

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    public class Client
    {
        public static void main(String args[])
        {
        InvocationHandler handler =null;
        AbstractSubject subject=null;
        
        handler=new DynamicProxy(new RealSubjectA());
        subject=(AbstractSubject)Proxy.newProxyInstance(AbstractSubject.class.getClassLoader(), new Class[]{AbstractSubject.class}, handler);
        subject.request();
        
        System.out.println("------------------------------");
        
        handler=new DynamicProxy(new RealSubjectB());
        subject=(AbstractSubject)Proxy.newProxyInstance(AbstractSubject.class.getClassLoader(), new Class[]{AbstractSubject.class}, handler);
        subject.request();
        } 
    }

    运行结果

    调用之前!
    真实主题类A!
    调用之后!
    ------------------------------
    调用之前!
    真实主题类B!
    调用之后!

    对于动态代理,我还有些困惑,写得不是很详细,正在慢慢学习中。。

  • 相关阅读:
    Vue 项目中 ESlint 配置
    ajax、axios、fetch 对比
    vue 中 axios 使用
    NodeJS 多版本管理(NVM)
    axio 请求中参数是数组
    Python 图片文字识别
    .NET 使用 VLC 播放视频
    Python 常见问题
    SpringBoot(4) SpringBoot热部署
    SpringBoot(3) 文件上传和访问
  • 原文地址:https://www.cnblogs.com/miantiaoandrew/p/9086874.html
Copyright © 2020-2023  润新知