【设计模式】【结构型模式(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. 可能影响性能:如果代理对象中的额外操作过于复杂,可能会影响系统的性能。
适用场景
  • 当需要在访问对象时添加额外的操作,如权限检查、日志记录等。
  • 当需要延迟初始化昂贵的对象,以提高系统性能。
  • 当需要控制对对象的访问,例如限制访问次数或频率。
  • 当需要为对象提供一个安全的访问点,例如网络服务的代理。
相关推荐
请你打开电视看看6 小时前
观察者模式
java·观察者模式·设计模式
Mr.朱鹏6 小时前
设计模式之策略模式-工作实战总结与实现
java·spring·设计模式·kafka·maven·策略模式·springbbot
春风十里不如你95277 小时前
【设计模式】【结构型模式(Structural Patterns)】之组合模式(Composite Pattern)
设计模式·组合模式
捕鲸叉7 小时前
C++设计模式之组合模式实践原则
c++·设计模式·组合模式
阿熊不会编程7 小时前
【计网】自定义协议与序列化(一) —— Socket封装于服务器端改写
linux·开发语言·网络·c++·设计模式
春风十里不如你95277 小时前
【设计模式】【行为型模式(Behavioral Patterns)】之责任链模式(Chain of Responsibility Pattern)
java·设计模式·责任链模式
博风8 小时前
设计模式:11、迭代器模式(游标)
设计模式·迭代器模式
春风十里不如你95279 小时前
【设计模式】【行为型模式(Behavioral Patterns)】之命令模式(Command Pattern)
设计模式·命令模式
岳轩子12 小时前
23种设计模式之原型模式
设计模式·原型模式