设计模式之结构型模式(四)代理模式

78 阅读2分钟

1.适配器模式 2.桥接模式 3.组合模式 4.代理模式 5.装饰模式 6.外观模式 7.享元模式

由于学习难度较大 并且相对用途较少 本章不会讲解享元模式

接下来针对以上6种设计模式进行单独讲解

4 代理模式

4.1 定义

给某一个对象提供一个代理,由代理对象控制原对象的引用。

此模式一般用于客户端由于一些原因不想或者不能访问目标对象,此时可以通过一个第三方的代理提供对目标对象的访问,该代理持有目标对象,客户端访问代理,代理访问目标对象。 并且在访问代理时也可以提供一些原有目标对象不具有的能力,比如要访问一个日志查询系统,可以通过代理来实现对该访问的鉴权追踪等。

4.2 UML图

image.png 从上面UML图中可以看出

Subject为抽象主题类,声明了真实主题和代理主题的共同接口,使得在任何使用真实主题的地方都能使用proxy进行替换

Proxy为代理主题类,代理主题内部持有真实主题的引用,从而保证在任何时候都可以通过代理访问真实主题。并且代理主题可以对真实主题的方法进行拓展。

RealSubject为客户端要访问的真实的主题

4.3 代码实现

// 抽象subject  
abstract class Subject {  
    public abstract void request();  
}  
  
// 真实主题RealSubject  
class RealSubject extends Subject {  
    @Override  
    public void request() {  
        System.out.println("Real subject requested at " + LocalDateTime.now());  
    }  
}  
  
// 代理角色Proxy  
class Proxy extends Subject {  
    private RealSubject realSubject;  
  
    public Proxy(RealSubject realSubject) {  
        this.realSubject = realSubject;  
    }  
  
    @Override  
    public void request() {  
        preRequest();  
        realSubject.request();  // 调用真实主题的request方法  
        postRequest();  
    }  
  
    private void preRequest() {  
        System.out.println("Pre-request actions before real request at " + LocalDateTime.now());  
    }  
  
    private void postRequest() {  
        System.out.println("Post-request actions after real request at " + LocalDateTime.now());  
    }  
}  
// 客户端Client  
public class Client {  
    public static void main(String[] args) {  
        RealSubject realSubject = new RealSubject();  // 创建真实主题对象  
        Proxy proxy = new Proxy(realSubject);  // 创建代理对象,并将真实主题传入代理对象中  
        proxy.request();  // 调用代理的request方法,会依次触发preRequest-真实主题的request-postRequest的顺序  
    }  
}

4.4 拓展

静态代理和动态代理

静态代理便类似上述例子所示,客户端通过Proxy调用RealSubject的request方法,此案例有先决条件便是真实的主题已经事先存在,代理类的接口和要代理的方法是事先确定好的。如果要为不同的真实主题提供代理,那么需要预先增加代理类。

动态代理便是解决了上述问题,动态代理可以让系统根据实际运行状况来动态的创建系统所需要的代理类,让同一个代理类能够代理不同的主题类(例如cglib等)。