【设计模式】【结构型模式(Structural Patterns)】之代理模式(Proxy Pattern)

1. 设计模式原理说明

代理模式(Proxy Pattern) 是一种结构型设计模式,允许你提供一个替身或占位符对象来控制对另一个对象的访问。代理模式的主要目的是控制对真实对象的访问,可以用来添加额外的功能(如延迟加载、权限检查等),而不改变客户端的代码。代理模式通常涉及四个角色:

  1. Subject(主题接口):定义了RealSubject和Proxy的共同接口,这样在任何使用RealSubject的地方都可以使用Proxy。
  2. RealSubject(真实主题):定义了代理对象代表的真实对象,负责执行实际的业务逻辑。
  3. Proxy(代理):持有对RealSubject的引用,可以通过这个引用调用RealSubject的方法。代理可以在调用前后执行额外的操作,比如权限检查、日志记录等。
  4. Client(客户端):通过Subject接口与RealSubject或Proxy交互。

2. UML 类图及解释

UML 类图
+-------------------+                +-----------------------+
|      Subject      |                |    RealSubject        |
|-------------------|                |-----------------------|
| - request(): void |                | - request(): void     |
+-------------------+                +-----------------------+
                  ^                        ^
                  |                        |
                  +------------------------+
                                 |
                                 |
+-----------------------------+  |
|           Proxy             |  |
|-----------------------------|  |
| - subject: Subject          |  |
| - request(): void           |  |
+-----------------------------+  |
类图解释
  • Subject:定义了一个公共接口,使得RealSubject和Proxy可以互换使用。
  • RealSubject:实现了Subject接口,定义了真实的业务逻辑。
  • Proxy:也实现了Subject接口,持有一个指向RealSubject的引用。可以在调用RealSubject的方法之前或之后执行额外的操作,例如权限检查、日志记录等。
  • Client:通过Subject接口与RealSubject或Proxy交互,无需关心具体的实现细节。

3. 代码案例及逻辑详解

Java 代码案例
// 主题接口
interface Subject {
    void request();
}

// 真实主题
class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}

// 代理
class Proxy implements Subject {
    private RealSubject realSubject;

    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        // 在调用真实主题的方法之前,可以添加额外的逻辑
        checkAccess();
        realSubject.request();
        // 在调用真实主题的方法之后,可以添加额外的逻辑
        logAccess();
    }

    private void checkAccess() {
        System.out.println("Proxy: Checking access prior to firing a real request.");
    }

    private void logAccess() {
        System.out.println("Proxy: Logging the time of request.");
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        Proxy proxy = new Proxy(realSubject);

        // 客户端通过代理来访问真实主题
        proxy.request();
    }
}
C++ 代码案例
#include <iostream>

// 主题接口
class Subject {
public:
    virtual void request() = 0;
    virtual ~Subject() {}
};

// 真实主题
class RealSubject : public Subject {
public:
    void request() override {
        std::cout << "RealSubject: Handling request.\n";
    }
};

// 代理
class Proxy : public Subject {
private:
    RealSubject* realSubject;
public:
    Proxy(RealSubject* realSubject) : realSubject(realSubject) {}

    void request() override {
        checkAccess();
        realSubject->request();
        logAccess();
    }

private:
    void checkAccess() {
        std::cout << "Proxy: Checking access prior to firing a real request.\n";
    }

    void logAccess() {
        std::cout << "Proxy: Logging the time of request.\n";
    }
};

// 客户端
int main() {
    RealSubject* realSubject = new RealSubject();
    Proxy* proxy = new Proxy(realSubject);

    // 客户端通过代理来访问真实主题
    proxy->request();

    delete realSubject;
    delete proxy;
    return 0;
}
Python 代码案例
# 主题接口
class Subject:
    def request(self):
        raise NotImplementedError

# 真实主题
class RealSubject(Subject):
    def request(self):
        print("RealSubject: Handling request.")

# 代理
class Proxy(Subject):
    def __init__(self, real_subject: RealSubject):
        self._real_subject = real_subject

    def request(self):
        # 在调用真实主题的方法之前,可以添加额外的逻辑
        self._check_access()
        self._real_subject.request()
        # 在调用真实主题的方法之后,可以添加额外的逻辑
        self._log_access()

    def _check_access(self):
        print("Proxy: Checking access prior to firing a real request.")

    def _log_access(self):
        print("Proxy: Logging the time of request.")

# 客户端
if __name__ == "__main__":
    real_subject = RealSubject()
    proxy = Proxy(real_subject)

    # 客户端通过代理来访问真实主题
    proxy.request()
Go 代码案例
package main

import (
	"fmt"
)

// 主题接口
type Subject interface {
	request()
}

// 真实主题
type RealSubject struct{}

func (r *RealSubject) request() {
	fmt.Println("RealSubject: Handling request.")
}

// 代理
type Proxy struct {
	realSubject *RealSubject
}

func (p *Proxy) request() {
	// 在调用真实主题的方法之前,可以添加额外的逻辑
	p.checkAccess()
	p.realSubject.request()
	// 在调用真实主题的方法之后,可以添加额外的逻辑
	p.logAccess()
}

func (p *Proxy) checkAccess() {
	fmt.Println("Proxy: Checking access prior to firing a real request.")
}

func (p *Proxy) logAccess() {
	fmt.Println("Proxy: Logging the time of request.")
}

// 客户端
func main() {
	realSubject := &RealSubject{}
	proxy := &Proxy{realSubject: realSubject}

	// 客户端通过代理来访问真实主题
	proxy.request()
}

4. 总结

代理模式 是一种结构型设计模式,允许你提供一个替身或占位符对象来控制对另一个对象的访问。这种模式的主要目的是在不改变客户端代码的情况下,添加额外的功能,如延迟加载、权限检查、日志记录等。

主要优点
  1. 职责分离:将复杂的操作封装在代理对象中,使客户端代码更加简洁。
  2. 增强功能:可以在不修改原始对象的情况下,通过代理对象添加额外的功能。
  3. 控制访问:可以限制对真实对象的访问,例如权限检查。
  4. 延迟初始化:可以延迟真实对象的创建,直到真正需要时才创建,从而节省资源。
主要缺点
  1. 增加了系统的复杂性:引入了额外的类和对象,使得系统更加复杂。
  2. 可能影响性能:如果代理对象中的额外操作过于复杂,可能会影响系统的性能。
适用场景
  • 当需要在访问对象时添加额外的操作,如权限检查、日志记录等。
  • 当需要延迟初始化昂贵的对象,以提高系统性能。
  • 当需要控制对对象的访问,例如限制访问次数或频率。
  • 当需要为对象提供一个安全的访问点,例如网络服务的代理。
相关推荐
等一场春雨30 分钟前
Java设计模式 八 适配器模式 (Adapter Pattern)
java·设计模式·适配器模式
晚秋贰拾伍2 小时前
设计模式的艺术-命令模式
运维·设计模式·运维开发·命令模式·开闭原则
ZoeLandia2 小时前
从前端视角看设计模式之行为型模式篇
前端·设计模式
晚秋贰拾伍4 小时前
设计模式的艺术-迭代器模式
设计模式·迭代器模式
小肚肚肚肚肚哦6 小时前
函数式编程中各种封装的对比以及封装思路解析
前端·设计模式·架构
等一场春雨18 小时前
Java设计模式 九 桥接模式 (Bridge Pattern)
java·设计模式·桥接模式
等一场春雨1 天前
Java设计模式 十四 行为型模式 (Behavioral Patterns)
java·开发语言·设计模式
小王子10241 天前
设计模式Python版 单例模式
python·单例模式·设计模式
_DCG_1 天前
c++常见设计模式之装饰器模式
c++·设计模式·装饰器模式
快乐非自愿1 天前
「全网最细 + 实战源码案例」设计模式——单例设计模式
java·单例模式·设计模式