当前位置: 首页 > article >正文

【设计模式】【结构型模式(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. 可能影响性能:如果代理对象中的额外操作过于复杂,可能会影响系统的性能。
适用场景
  • 当需要在访问对象时添加额外的操作,如权限检查、日志记录等。
  • 当需要延迟初始化昂贵的对象,以提高系统性能。
  • 当需要控制对对象的访问,例如限制访问次数或频率。
  • 当需要为对象提供一个安全的访问点,例如网络服务的代理。

http://www.kler.cn/a/412722.html

相关文章:

  • urllib3只支持OpenSSL1.1.1
  • Dart 中 initializer lists
  • 15分钟做完一个小程序,腾讯这个工具有点东西
  • 对比 MyBatis 批处理 BATCH 模式与 INSERT INTO ... SELECT ... UNION ALL 进行批量插入
  • Elasticsearch中的节点(比如共20个),其中的10个选了一个master,另外10个选了另一个master,怎么办?
  • 银行卡 OCR 识别 API 接口的发展前景
  • Python 网络爬虫入门教程:理论与实践
  • Spring Boot开发实战:从入门到构建高效应用
  • Spark垃圾回收
  • 活着就好20241128
  • 【设计模式】【结构型模式(Structural Patterns)】之外观模式(Facade Pattern)
  • 医学机器学习:数据预处理、超参数调优与模型比较的实用分析
  • T3 TensorFlow入门实战——天气识别
  • laravel-operate
  • 数学期望在算法中的应用
  • 开源 - Ideal库 - Excel帮助类,设计思路(一)
  • 【人工智能】使用Python实现序列到序列(Seq2Seq)模型进行机器翻译
  • Ollama - 简化使用本地大语言模型
  • 双十一线上服务调用链路追踪SkyWalking实战分析
  • PostgreSQL表膨胀问题解析
  • python-docx -- 读取word页眉、页脚
  • 上海迪士尼奇幻冬日巡游:IP营销如何出圈?
  • wordpress拖拽式自定义文章排序插件Simple Custom Post Order,支持对wordpress文章、页面、自定义文章进行自定义排序
  • 通信与网络安全之IPSEC
  • [DL]深度学习_扩散模型正弦时间编码
  • 关于如何在k8s中搭建一个nsfw黄图鉴定模型