设计模式-代理模式

代理模式

包括

      静态代理:是在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);
    }

}

 时序图如下

 

 

 

 

 
 
 
posted @ 2020-12-23 12:21  wf.zhang  阅读(89)  评论(0编辑  收藏  举报