设计模式(6)代理模式

1.什么是代理模式

   编程中有一个思想就是不要随意修改别人的代码,如果需要修改,可以通过代理模式来实现

   用户------代理对象--------目标对象(被代理对象)

 

2.静态代理

   静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或继承相同的父类

  缺点:代理对象和目标对象需要实现同一个接口,所以一旦增加接口中的方法,代理对象和目标对象都需要修改

//接口
public interface IUser {
    void say();
}

//目标对象
public class User implements IUser{

    @Override
    public void say() {
        System.out.println("target Object...");
    }
}

//代理对象
public class UserProxy implements IUser {
    //保存目标对象
    private User target;

    public UserProxy(User target){
        this.target = target;
    }
    @Override
    public void say() {
        System.out.println("add Proxy Object...");
        target.say();
    }
}

//测试类
public class Test {
    public static void main(String[] args) {
        //目标对象
        User target = new User();
        //代理对象
        UserProxy proxy = new UserProxy(target);

        proxy.say();
    }
}

 

 

3.动态代理-JDK代理

利用JDK的API,动态的在内存中构建代理对象(java.lang.reflect.Proxy)

缺点:代理对象虽然不需要实现接口,但是目标对象需要实现接口,否则不能用动态代理

public class Client {
    public static void main(String[] args) {
        Producer producer = new Producer();

        /*
         *  基于接口:
         *       涉及的类:Proxy(JDK官方提供)
         *       创建代理对象:Proxy.newInstance()
         *       要求:被代理对象至少实现一个接口
         *       newProxyInstance的三个参数:
         *       (1)classLoader:被代理对象类加载器(用来去加载代理对象)
         *       (2)class[]: 代理对象需要实现的接口
         *       (3)InvocationHandler:用于提供增强的代码 被代理类中的任何方法都会经过create方法
         *           其中invoke三个参数:object:代理对象的引用   method:当前执行的方法   objects[]:当前执行方法所需的参数
         *
         */
        IProducer proxyInstance = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(),
                producer.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                        Object returnValue = null;
                        Float money = (Float) objects[0];

                        if ("saleProduct".equals(method.getName())) {
                            returnValue = method.invoke(producer, money * 0.8f);
                        }
                        return returnValue;
                    }
                });
        proxyInstance.saleProduct(1000f);
    }
}

 

4.动态代理-Cglib代理

(1)以目标代理对象子类的方式实现代理,这种方法叫Cglib代理(底层是对字节码处理框架ASM来转换字节码并生成新的类)

(2)实现方法:首先要引入cglib的jar包,spring核心包中已包含cglib功能,所以引入spring核心包即可

     在Spring的AOP编程中:
          如果加入容器的目标对象有实现接口,用JDK代理
          如果目标对象没有实现接口,用Cglib代理

public class Client {
    public static void main(String[] args) {
        Producer producer = new Producer();

    /*
    *   基于子类:
    *       涉及的类:Enhancer(第三方cglib库)
    *       创建代理对象:Enhancer.create()
    *       要求:被代理对象不能是最终类
    *       create的参数:
    *       (1)class字节码:被代理对象的字节码
    *       (2)Callback:用于提供增强的代码。一般用该接口的子接口:MethodOInterceptor 被代理类中的任何方法都会经过intercept方法
    *        前三个参考invoke,第四个为当前执行方法的代理对象
    *
    *
    */
        Producer cglibProducer = (Producer)Enhancer.create(producer.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object returnValue = null;
                Float money = (Float) objects[0];

                if ("saleProduct".equals(method.getName())) {
                    returnValue = method.invoke(producer, money * 0.8f);
                }
                return returnValue;
            }
        });
        cglibProducer.saleProduct(1000f);
    }
}

                   

5. 代理模式和装饰者模式的区别

装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问

  装饰器模式:需要传入 被装饰者 对象实例。你是知道这个要被装饰的对象的

  代理模式:被代理者是 在代理类中 new 出来的,你不需要传入 被代理对象, 也就是说你不知道 被代理对象是谁

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值