bacor

个人站

Coding is important, so is writing


代理模式

代理模式也叫委托模式,为其他对象提供一种代理以控制对这个对象的访问。状态模式、策略模式、访问者模式本质上是在更特殊的场合采用代理模式。

应用场景

防止直接访问目标对象带来的不必要复杂性 面向切面编程(AOP)

定义

UML图如下: ![]((/images/posts/designpattern/proxy.png)

实现

Subject类

public interface Subject {
    void doSomething();
}

RealSubject类

public class RealSubject implements Subject{
    @Override
    public void doSomething() {
        //业务逻辑
    }
}

代理类

public class Proxy implements Subject {
    private Subject subject;

    public Proxy(){
        this.subject = new Proxy();
    }
    public Proxy(Subject subject){
        this.subject = subject;
    }

    private void before(){
        //预处理
    }

    private void after(){
        //后续处理
    }

    @Override
    public void doSomething() {
        before();
        this.subject.doSomething();
        after();
    }
}

动态代理

可以发现,在上面代理模式的实现中虽然可以产生代理对象,但是这样做的代价是当要代理多种对象时,就需要为每种对象实现代理对象。为了解决对象量多、代码量大的问题,进一步可拓展为动态代理

动态代理的实现

InvocationHandler的实现(动态代理核心)

public class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object object){
        this.target = object;
    }

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

通知的实现

public interface IAdvice {
    void exec();
}
public class BeforeAdvice implements IAdvice {
    @Override
    public void exec() {
        //前置通知
    }
}

产生动态代理对象

public class DynamicProxy<T> {
    public static <T> T newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h){
        //寻找连接点
        if(true){
            //执行前置通知
            (new BeforeAdvice()).exec();
        }
        //返回结果
        return (T) Proxy.newProxyInstance(loader,interfaces,h);
    }
}

Client类

public class Client {
    public static void main(String[] args) {
        Subject subject = new RealSubject();
        InvocationHandler handler = new MyInvocationHandler(subject);
        Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(),
                subject.getClass().getInterfaces(),handler);
        //代理执行
        proxy.doSomething();
    }
}

整一个调用过程如下:

优点

  • 职责清晰,降低系统耦合度
  • 高扩展性

缺点

  • 增加代理对象,降低请求速度和增加代码
  • 动态代理使用到反射,运行效率降低

参考

代理模式(Proxy Pattern):静态代理 - 最易懂的设计模式解析 设计模式之禅