设计模式-代理模式(Proxy)

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/love905661433/article/details/84427343

代理模式(Proxy)

  • 定义 : 为其他对象提供一种代理, 以控制对这个对象的访问
  • 代理对象在客户端和目标对象之间起到中介的作用
  • 类型 : 结构型

适用场景

  • 保护目标对象
  • 增强目标对象

优点

  • 代理模式能将代理对象与真实被调用的目标对象分离
  • 一定程度上降低了系统的耦合度, 扩展性好
  • 保护目标对象
  • 增强目标对象

缺点

  • 造成系统设计中类的数目增加
  • 在客户端和目标对象之间增加了一个代理对象, 会造成一定的性能下降
  • 增加了系统的复杂度

扩展

  • 静态代理
  • 动态代理 : 只能代理实现了接口的类
  • CGLib代理 : 通过继承实现的, 所以要注意final关键字

Spring代理选择

  • 当Bean中有实现接口时, Spring就会用JDK的动态代理

  • 当Bean中没有实现接口时, Spring使用CGLib

  • 也可以强制使用CGLib, 增加如下配置即可:

    <aop : aspectj-autoproxy proxy-target-class="true"/>
    

模式角色

  • Proxy :

    • 保存一个引用使得代理可以访问实体。若 RealSubject和Subject的接口相同,Proxy会
      引用Subject。
    • 提供一个与Subject的接口相同的接口,这样代理就可以用来替代实体。
    • 控制对实体的存取,并可能负责创建和删除它。
    • 控制对实体的存取,并可能负责创建和删除它。
  • Subject : 定义RealSubject 和Proxy 的共用接口,这样就在任何使用 RealSubject的地方都可以使
    用Proxy。

  • RealSubject : 定义Proxy所代表的实体

代码实现

静态代理

UML类图:
在这里插入图片描述

对应各模块代码:

/**
 * @author 七夜雪
 * @create 2018-11-24 9:31
 */
public interface Subject {
    public void showName();

}
/**
 * 被代理类
 *
 * @author 七夜雪
 * @create 2018-11-24 9:30
 */
public class RealSubject implements Subject {

    @Override
    public void showName() {
        System.out.println("被代理类方法---");
    }
}
/**
 * 代理类
 *
 * @author 七夜雪
 * @create 2018-11-24 9:32
 */
public class Proxy implements Subject {
    private RealSubject realSubject = new RealSubject();

    @Override
    public void showName() {
        System.out.println("被代理类方法执行之前执行...");
        realSubject.showName();
        System.out.println("被代理类方法执行之后执行...");
    }
}

测试类 :

/**
 * 测试类
 *
 * @author 七夜雪
 * @create 2018-11-24 9:34
 */
public class Client {

    public static void main(String[] args) {
        Subject subject = new Proxy();
        subject.showName();
    }
}

测试结果 :

被代理类方法执行之前执行...
被代理类方法---
被代理类方法执行之后执行...

动态代理

这里就以JDK的动态代理为例, 要实现JDK的动态代理, 就需要实现InvocationHandler接口, 下面是具体代码实现:
动态代理类 :

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理
 *
 * @author 七夜雪
 * @create 2018-11-24 9:55
 */
public class DynamicProxy implements InvocationHandler {
    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    public Object bind(){
        Class cls = target.getClass();
        return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        beforeMethod();
        Object invoke = method.invoke(target, args);
        afterMethod();
        return invoke;
    }

    private void beforeMethod(){
        System.out.println("动态代理 before code");
    }

    private void afterMethod(){
        System.out.println("动态代理 after code");
    }
}

Subject接口 :

/**
 * @author 七夜雪
 * @create 2018-11-24 9:31
 */
public interface Subject {
    public void showName();

}

Subject接口的两个实现类, 即被代理的类 :

/**
 * 被代理类
 *
 * @author 七夜雪
 * @create 2018-11-24 9:30
 */
public class RealSubject1 implements Subject {

    @Override
    public void showName() {
        System.out.println("被代理类方法1---");
    }
}
/**
 * 被代理类
 *
 * @author 七夜雪
 * @create 2018-11-24 9:30
 */
public class RealSubject1 implements Subject {

    @Override
    public void showName() {
        System.out.println("被代理类方法2---");
    }
}

测试代码 :

/**
 * 测试类
 *
 * @author 七夜雪
 * @create 2018-11-24 9:34
 */
public class Client {

    public static void main(String[] args) {
        Subject proxy1 = (Subject) new DynamicProxy(new RealSubject1()).bind();
        Subject proxy2 = (Subject) new DynamicProxy(new RealSubject2()).bind();
        proxy1.showName();
        proxy2.showName();
    }
}

测试结果 :

动态代理 before code
被代理类方法1---
动态代理 after code
动态代理 before code
被代理类方法2---
动态代理 after code

本文参考:
慕课网<java设计模式精讲 Debug 方式+内存分析>课程
四人帮<设计模式>

猜你喜欢

转载自blog.csdn.net/love905661433/article/details/84427343