设计模式之代理模式

代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理模式可以在不修改原始对象的情况下,添加额外的功能或处理逻辑。

使用场景

  1. 控制对复杂或敏感对象的访问
    当需要控制对某些复杂或敏感对象的访问时,可以使用代理模式来封装这些对象的访问逻辑。

    示例:虚拟代理(Virtual Proxy),用于控制对大型资源(如大文件或大图片)的访问,只有在真正需要时才加载这些资源。

  2. 延迟加载(Lazy Loading)
    当创建对象的开销很大时,可以使用代理模式延迟对象的创建,只有在第一次访问对象时才创建它。

    示例:在一个图形编辑器中,只有在用户真正需要查看大图片时,才会加载和显示这些图片。

  3. 提供远程对象的代理(Remote Proxy)
    当对象在不同的地址空间或远程服务器上时,可以使用代理模式来封装网络通信细节,使得客户端像访问本地对象一样访问远程对象。

    示例:RPC(远程过程调用)框架,客户端通过代理对象调用远程服务器上的方法。

  4. 为对象添加额外的功能
    代理模式可以在不修改原始对象的情况下,为对象添加额外的功能或处理逻辑。

    示例:保护代理(Protection Proxy),用于控制对敏感对象的方法调用,确保调用者具有适当的权限。

  5. 分离职责: 代理模式可以将实际工作与控制逻辑分开,使代码更清晰、更易于维护。

    示例:将访问控制、性能监测等职责从业务逻辑中分离出来。

UML类图

+-------------------+       +-------------------+
|    Subject        |<>---->|   Proxy           |
+-------------------+       +-------------------+
| +request()        |       | -realSubject: RealSubject |
+-------------------+       | +request()        |
                            +-------------------+
                                     /|\
                                      |
                                      |
                            +-------------------+
                            |   RealSubject     |
                            +-------------------+
                            | +request()        |
                            +-------------------+

示例代码

假设我们有一个图片查看器,当用户想查看大图片时,只有在真正需要时才加载图片。我们用代理模式来实现这个场景。

#include <iostream>
#include <memory>

// 抽象主题类
class Image {
public:
    virtual void display() = 0;
    virtual ~Image() = default;
};

// 真实主题类
class RealImage : public Image {
public:
    RealImage(const std::string& filename) : filename_(filename) {
        loadFromDisk();
    }

    void display() override {
        std::cout << "Displaying " << filename_ << std::endl;
    }

private:
    void loadFromDisk() {
        std::cout << "Loading " << filename_ << " from disk..." << std::endl;
    }

    std::string filename_;
};

// 代理类
class ProxyImage : public Image {
public:
    ProxyImage(const std::string& filename) : filename_(filename) {}

    void display() override {
        if (!realImage_) {
            realImage_ = std::make_unique<RealImage>(filename_);
        }
        realImage_->display();
    }

private:
    std::string filename_;
    std::unique_ptr<RealImage> realImage_;
};

// 客户端代码
int main() {
    std::unique_ptr<Image> image = std::make_unique<ProxyImage>("large_image.jpg");

    // 图片第一次显示时,加载并显示图片
    image->display();

    // 图片第二次显示时,不需要重新加载,直接显示
    image->display();

    return 0;
}

代码解读

  1. 抽象主题类(Image):定义了 display 方法,所有具体主题和代理类都需要实现这个方法。
  2. 真实主题类(RealImage):实现了 Image 接口,包含加载和显示图片的逻辑。在构造函数中加载图片。
  3. 代理类(ProxyImage):也实现了 Image 接口,持有一个 RealImage 对象的指针。在第一次调用 display 方法时,创建并加载 RealImage 对象,后续调用直接使用已经加载的对象。
  4. 客户端代码:通过代理类 ProxyImage 访问和显示图片。第一次调用 display 时加载图片,后续调用直接显示。

使用场景总结

  1. 控制对复杂或敏感对象的访问:如虚拟代理控制对大型资源的访问。
  2. 延迟加载(Lazy Loading):如在图形编辑器中延迟加载大图片。
  3. 提供远程对象的代理(Remote Proxy):如RPC框架中的远程方法调用。
  4. 为对象添加额外的功能:如保护代理控制对敏感对象的方法调用。
缺点
  • 增加系统复杂性: 代理模式引入了额外的代理类和代理对象,使系统结构变得更加复杂,增加了理解和维护的难度。

    示例:对于简单的对象访问,引入代理模式可能显得过于复杂和冗余。

  • 性能开销: 代理模式会增加一些额外的处理开销,如方法调用的间接性和对象的创建时间等,可能会影响系统性能。

    示例:对于需要频繁访问的对象,代理模式可能带来性能上的额外开销。

  • 实现成本: 代理模式的实现需要额外的代码和逻辑,如代理类的实现和方法的重定向等,增加了开发成本。

    示例:实现远程代理时,需要处理网络通信、序列化和反序列化等复杂逻辑。

通过这些例子和解释,可以看到代理模式在控制对象访问、延迟加载、提供远程对象代理以及为对象添加功能方面的强大功能,同时也要注意它可能带来的复杂性和性能开销。

代理模式是一种结构型设计模式,它提供一个代理对象来代表另一个对象。在代理模式中,有一个被称为实际对象(Subject)和一个被称为代理对象(Proxy)的中介,代理对象持有实际对象的引用,并且可以控制对实际对象的访问。代理模式的主要目的是在不修改原始对象的情况下,为原始对象添加额外的逻辑处理。 代理模式分为多种类型,如远程代理、虚拟代理、保护代理等,它们各自有不同的应用场景: - 远程代理:为远程对象提供一个本地代表。 - 虚拟代理:根据需要创建开销大的对象,通过虚拟代理控制访问这些对象的过程。 - 保护代理:控制对原始对象的访问权限,例如进行权限检查。 代理模式的优点包括: 1. 能够控制对真实对象的访问,并在访问前后添加额外的逻辑。 2. 可以通过代理对象实现延迟加载,即在实际需要时才创建真实对象。 3. 增强了对真实对象的封装,并且可以避免对真实对象的重复引用。 在C#中实现代理模式通常涉及以下步骤: 1. 定义一个接口或抽象类,声明真实对象和代理对象需要实现的方法。 2. 实现真实对象的类,按照接口或抽象类的要求实现具体方法。 3. 实现代理类,它同样实现接口或抽象类,并在方法中持有真实对象的引用,通过调用真实对象的方法来执行所需的操作,同时可以添加额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值