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

    代理模式

    包括

          静态代理:是在java文件编译前,手动写好代理类并绑定了代理关系,  所以只能代理绑定的类或接口。

            动态代理:是通过反射原理,在程序运行的时候动态的生成的代理对象,所以可以代理任意的类或对象。

    代理模式作用  为目标对象提供一个代理对象,并由代理对象控制对目标对象的调用    类似于中介

    静态代理:是在java文件编译前,手动写好代理类并绑定了代理关系,  所以只能代理绑定的类或接口。

            有接口/功能 (声明业务方法)     

                      被代理类(用户) implement 实现 这个接口/功能  重写方法 (具体自己业务方法)

                      代理类 也要implement 实现 这个功能/接口 

                          构造注入这个接口/功能(目标对象)

                          重写方法中

                          调用目标对象的业务方法   并附加其他方法(做其他事情)

     例1

    public interface Buyer {
        /**
         * 查看房屋
         * @return 反馈
         */
        public String havealook();
    }
    Buyer
    public class RealBuyer implements Buyer {
        @Override
        public String havealook() {
            System.out.println("*****实地查看一下");
            return "*****一些意见";
        }
    }
    RealBuyer
    public class IntermediaryImpl implements Buyer {
        /**
         * 被代理的目标对象
         */
        private Buyer target;
    
        public IntermediaryImpl(Buyer target) {
            this.target = target;
        }
    
        /**
         * 对目标对象业务进行代理
         */
        @Override
        public String havealook() {
            before();
            String feedback = target.havealook(); // 执行目标对象的实际业务
            after();
            return "看房记录:买家反馈“" + feedback + "”";
        }
    
        public void before() {
            System.out.println("前期准备。");
            System.out.println("查找房源。");
            System.out.println("和卖家沟通时间。");
        }
        public void after() {
            System.out.println("后期跟踪");
            System.out.println("和买家沟通意见。");
        }
    }
    IntermediaryImpl
    public class BuyerTest {
        public static void main(String[] args) throws Exception {
            RealBuyer user=new RealBuyer();//创建真是用户
            Buyer buyer = new IntermediaryImpl(user);//创建代理对象[中介],将被代理者交给中介 管理
            String result = buyer.havealook();
            System.out.println(result);
        }
    }

    时序图如下

    例2

    public class Movie {
        public static String payTicket(int vip,String ticketName){
            try {
                if (vip==0) {
                    Thread.sleep(5000);
                }else if (vip==1) {
                    Thread.sleep(4000);
                }else if (vip==2) {
                    Thread.sleep(2000);
                }else if (vip==3) {
    
                }
            } catch (Exception e) {
                // TODO: handle exception
            }
            return ticketName+" 购买成功!";
        }
    }
    Movie
    public interface User {
        /**
         * 购买电影票
         * @return
         */
        public String buyTicket();
    }
    User
    public class RealUser implements User{
        public String buyTicket() {
            System.out.println("排队中....");
            return "电影票: 火影忍者";
        }
        /**
         * 0级 VIP
         * @return
         */
        public int getVIP() {
            return 0;
        }
    }
    RealUser
    public class YellowCattle implements User {
        private User user;
        public YellowCattle(User user) {
            this.user = user;
        }
        
        @Override
        public String buyTicket() {
            //增加额外功能
            //管理被代理者: 辅助他完成功能
            String ticketInfo=user.buyTicket();
            Movie obj=new Movie();
            String rs=obj.payTicket(getVIP(), ticketInfo);
            return rs;
        }
        /**
         * 3级 VIP
         * @return
         */
        public int getVIP() {
            return 3;
        }
    }
    YellowCattle
    public class TicketTest {
        public static void main(String[] args) {
            //创建真实用户
            User user=new RealUser();
            //创建代理对象
            YellowCattle obj=new YellowCattle(user);//将被代理者 交给 代理对象管理
    
            String str=obj.buyTicket();
            System.out.println("<===找黄牛买票===>"+str);
            /**
             * 不希望用户接触 或 用户不善长的功能 --->交给代理对象完成.
             */
            RealUser realUser=new RealUser();
            String result2= Movie.payTicket(realUser.getVIP(), realUser.buyTicket());
            System.out.println("<****自己买票****>" +result2);
        }
    }

     时序图如下

            没有接口/功能(作为功能类的方法存在)   

                          功能类          必须满足一定条件 (特殊属性)  要完成的方法

                       被代理类(用户)   要完成的方法   (一般属性)

                       代理类extends 继承被代理对象     代理类有(特殊属性)

                        重写方法中

                        通过功能类 调用 代理类特殊属性  被代理对象要完成的方法

    public class Movie {
        public static String payTicket(int vip,String ticketName){
            try {
                if (vip==0) {
                    Thread.sleep(5000);
                }else if (vip==1) {
                    Thread.sleep(4000);
                }else if (vip==2) {
                    Thread.sleep(2000);
                }else if (vip==3) {
                    
                }
            } catch (Exception e) {
                // TODO: handle exception
            }
            return ticketName+" 购买成功!";
        }
        
    }
    Movie
    public class RealUser {
        public String buyTicket() {
            System.out.println("排队中....");
            return "电影票: 火影忍者";
        }
        /**
         * 0级 VIP
         * @return
         */
        public int getVIP() {
            return 0;
        }
    }
    RealUser
    public class YellowCattle extends RealUser {
        
        @Override
        public String buyTicket() {
            //增加额外功能
            //管理被代理者: 辅助他完成功能
            String ticketInfo=super.buyTicket();
            Movie obj=new Movie();
            String rs=obj.payTicket(getVIP(), ticketInfo);
            return rs;
        }
        /**
         * 3级 VIP
         * @return
         */
        public int getVIP() {
            return 3;
        }
    }
    YellowCattle
    public class TicketTest {
        public static void main(String[] args) {
            //创建代理对象
            YellowCattle obj=new YellowCattle();//将被代理者 交给 代理对象管理
            
            String str=obj.buyTicket();
            System.out.println(str);
            
        }
    }

     时序图如下

    动态代理:是通过反射原理,在程序运行的时候动态的生成的代理对象,所以可以代理任意的类或对象。

       JDK动态代理    InvocationHander接口  处理器

              有接口/功能 (声明业务方法)     (特殊属性)

                 被代理类(用户) implement 实现 这个接口/功能  重写方法 (具体自己业务方法) (一般属性)

                      代理类  implement 实现 InvocationHander接口         (特殊属性)

                          构造注入Object对象(目标对象)

                          重写方法invoke()中

                          通过反射调用目标对象的业务方法  得到方法参数

                          功能类调用 代理类   (特殊属性)  目标对象的返回值(恰好是功能类的参数)

             

    public class Movie {
        /**
         * 万达售票: 根据VIP级别排队购买电影票
         * @param vip
         * @param ticketName
         * @return
         */
        public static String payTicket(int vip,String ticketName){
            try {
                if (vip==0) {
                    Thread.sleep(5000);
                }else if (vip==1) {
                    Thread.sleep(4000);
                }else if (vip==2) {
                    Thread.sleep(2000);
                }else if (vip==3) {
                    
                }
            } catch (Exception e) {
                // TODO: handle exception
            }
            return ticketName+" 购买成功!";
        }
    }
    Movie
    public interface User {
        /**
         * 购买电影票
         * @return
         */
        public String buyTicket();
    }
    User
    public class RealUser implements User{
        public String buyTicket() {
            System.out.println("排队中....");
            return "电影票: 火影忍者";
        }
        /**
         * 0级 VIP
         * @return
         */
        public int getVIP() {
            return 0;
        }
    }
    RealUser
    public class IntermediaryInvocationHandler implements InvocationHandler {
        /**
         * 被代理的目标对象
         */
        private Object target;
        public void setTarget(Object target) {
            this.target = target;
        }
        /**
         * 为被代理的接口方法定义的代理业务规则
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            //Method对象.invoke(对象实例,参数): 反射方式,执行被代理对象的指定方法
            String ticketName = (String) method.invoke(target, args);
            String result= Movie.payTicket(getVIP(), ticketName);
            return result;
        }
        /**
         * 10级 VIP
         * @return
         */
        public int getVIP() {
            return 10;
        }
    }
    IntermediaryInvocationHandler
    public class TicketTest {
        public static void main(String[] args) throws Exception {
            //创建真实对象
            Object target=new RealUser();
            //创建 处理程序
            IntermediaryInvocationHandler handler = new IntermediaryInvocationHandler();
            //设置 处理程序操作的真实对象
            handler.setTarget(target);
            //获得代理对象: 根据指出的接口和真实类,以实现接口的方式为真实类创建代理对象.
            User user =(User) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), handler);
            //当使用代理对象访问方法时,会将方法调用指派给"处理程序[Handler]". 处理程序会执行invoke()
            String result = user.buyTicket();
            System.out.println(result);
        }
    
    }

     时序图如下

         CGLIB动态代理   MethodInterceptor接口  拦截器

              没有接口/功能(被代理类  自己的业务方法)

                    代理工厂类

                          实例化业务规则类

                          ctreate()方法中 

                                实例化Enhancer  回调业务规则对象 方法

                                将目标对象作为父类反射动态创建目标对象的子类

                    定义业务规则类 implement 实现 MethodInterceptor接口 

                        重写intercept()方法中

                        增加一些事情 并调用代理类的父类的方法

    新建lib文件夹 导入jar包  cglib-nodep-3.3.0.jar  log4j-1.2.17.jar

    新建resources文件夹

    # rootLogger是所有日志的根日志,修改该日志属性将对所有日志起作用
    # 下面的属性配置中,所有日志的输出级别是debug,输出源是con
    log4j.rootLogger=debug,con
    # 定义输出源的输出位置是控制台
    log4j.appender.con=org.apache.log4j.ConsoleAppender
    # 定义输出日志的布局采用的类
    log4j.appender.con.layout=org.apache.log4j.PatternLayout
    # 定义日志输出时间格式
    log4j.appender.con.layout.ConversionPattern=%d{MM-dd HH:mm:ss}[%p]%c - %m%n
    log4j.properties
    public class RealBuyer  {
        private Logger logger = Logger.getLogger(RealBuyer.class);
    
        public String havealook() {
            logger.debug("---->>>>>>>实地查看一下");
            return "---->>>>>>>一些意见";
        }
    }
    public class IntermediaryMethodInterceptor implements MethodInterceptor {
        private Logger logger = Logger.getLogger(IntermediaryMethodInterceptor.class);
        /**
         * 为被代理的方法定义的代理业务规则
         */
        @Override
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
                throws Throwable {
            before();
            Object feedback = methodProxy.invokeSuper(proxy, args); // 调用父类原始的方法
            after();
            return "看房记录:买家反馈“" + feedback + "”";
        }
    
        public void before() {
            logger.debug("前期准备。");
            logger.debug("查找房源。");
            logger.debug("和卖家沟通时间。");
        }
    
        public void after() {
            logger.debug("后期跟踪");
            logger.debug("和买家沟通意见。");
        }
    }
    public class IntermediaryCglibProxyFactory {
    
        //MethodInterceptor接口 实现类
        private static IntermediaryMethodInterceptor callback = new IntermediaryMethodInterceptor();
    
        /**
         * 工厂方法
         * @param target 需要被代理的类型,即代理类需要继承的父类型
         * @return 代理类的实例
         */
        public static <T> T create(Class<T> target) {
            //增强器
            //Enhancer负责动态生成代理 = 目标对象的子类
            Enhancer enhancer = new Enhancer();
            enhancer.setCallback(callback); // 为重写的方法指定回调的MethodInterceptor
            enhancer.setSuperclass(target); // 指定要继承的父类型,即需要被代理的类型
            return (T) enhancer.create(); // 动态生成子类,创建子类实例并返回
        }
    }
    public class BuyerTest {
        private Logger logger = Logger.getLogger(BuyerTest.class);
    
        @Test
        public void havealookCglibProxy() throws Exception {
            RealBuyer buyer = IntermediaryCglibProxyFactory.create(RealBuyer.class);
            String result = buyer.havealook();
            logger.debug(result);
        }
    
    }

     时序图如下

     
     
     
    古人学问无遗力,少壮工夫老始成。 纸上得来终觉浅,绝知此事要躬行。
  • 相关阅读:
    css3新特性合集
    前端面试必备的css盒子模型
    激动人心的第一天啊
    Simulink 自动代码生成原理
    什么是 Target Language Compiler
    A*算法 (MATLAB) -路径搜索
    路径搜索 – Dijkstra 算法 (MATLAB实现)
    客户端测试
    test
    【AtCoder Regular Contest 110 选做】D
  • 原文地址:https://www.cnblogs.com/wf-zhang/p/14177920.html
Copyright © 2011-2022 走看看