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

学习软件设计,向OO高手迈进!
设计模式(Design pattern)是软件开发人员在软件开发过程中面临的一般问题的解决方案。
这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
是前辈大神们留下的软件设计的"招式"或是"套路"。

什么是代理模式

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式,也就是说当客户端无法直接访问某个对象或访问某个对象存在困难时,可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象代理对象需要实现相同的接口。

举例说明,就是一个人或者一个机构,代表另一个人或者另一个机构采取行动。在一些情况下,客户端不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用。

定义

在代理模式中,我们为其他对象提供一种代理以控制对这个真实对象的访问。

直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的间接层,**“增加一层间接层”**是软件系统中对许多复杂问题的一种常见解决方法。

UML类图

在这里插入图片描述

代理模式中的角色:

  1. Subject(抽象主题角色):真实主题与代理主题的共同接口。
  2. RealSubject(真实主题角色):定义了代理角色所代表的真实对象。也叫做被委托角色被代理角色,是业务逻辑的具体执行者。
  3. Proxy(代理主题角色):含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真实主题对象之前或者之后执行某些操作,而不是单纯返回真实的对象。
  4. Client:客户类,使用代理对象的类。

Version 1.0

下面我们以送女朋友礼物来讲解该模式:

比如说你把你女朋友给惹毛了,这时候你直接去求原谅可能她不会鸟你。这怎么办?拿出手机,打开美
团跑腿,叫个外卖小哥给她送点礼物消消气,方便后面的行动。在这个例子中,你自己就是真实角色,外卖小哥就是代理你的角色,由他来代表你去送礼物,这就是代理的意思。

一、定义抽象主题类

// 抽象主题类(Subject)类
// 定义了 实际主题类(RealSubject)和代理类(Proxy)的共用接口
// 这样就可以在任何使用 RealSubject 的地方使用 Proxy
class GiveGift {
public:
    virtual ~GiveGift() = default;
    virtual void GiveDolls() = 0;
    virtual void GiveFlowers() = 0;
    virtual void GiveChocolate() = 0;
};

二、定义实际主题类

// 实际主题(RealSubject)类
// 定义了代理类(Proxy)真正需要调用的方法
// final 关键字 表明该类不能做一个基类
class RealGiveGift final : public GiveGift {
public:
    void GiveDolls() {
        cout << "give dolls" << endl;
    }
    void GiveFlowers() {
        cout << "give flowers" << endl;
    }
    void GiveChocolate() {
        cout << "give chocolate" << endl;
    }
};

三、定义代理类

// 代理类(Proxy),保存一个引用使的代理对可以访问实体
// 并提供一个与Subject的相同的接口,这样代理就可以用来替代实体
class MeiTuanProxy final : public GiveGift {
public:
    MeiTuanProxy() {
        m_RealObject = new RealGiveGift();
    }
    ~MeiTuanProxy() {
        delete m_RealObject;
        m_RealObject = nullptr;
    }
    void GiveDolls() {
        // do something
        m_RealObject->GiveDolls();
        // do something
    }
    void GiveFlowers() {
        // do something
        m_RealObject->GiveFlowers();
        // do something
    }
    void GiveChocolate() {
        // do something
        m_RealObject->GiveChocolate();
        // do something
    }
private:
    RealGiveGift *m_RealObject;
};

四、客户端

int main(int argc, char** argv) {
    MeiTuanProxy *meituan = new MeiTuanProxy();
    meituan->GiveDolls();
    meituan->GiveFlowers();
    meituan->GiveChocolate();
    delete meituan;
    meituan = nullptr;
    return 0;
}

执行结果

give dolls
give flowers
give chocolate

优点

  1. 可以实现客户类与委托类间的解耦,在不修改委托类代码的情况下能够做一些额外的处理。
  2. 代理模式能将代理对象与真实对象被调用的目标对象分离。
  3. 一定程度上降低了系统的耦合度,扩展性好 。

缺点

  1. 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
  2. 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

适用场合

从上面的示例和UML图看,先访问代理类再访问真正要访问的对象。似乎这样有点多此一举的味道,其实不然,这是有一定道理的。

代理类可以在真正的类执行之前,进行一些预处理。比如上面的示例中,外卖小哥看到有订单后,先判断一下要送到哪里,和自己当前位置远不远,要不要绕路等,然后再决定要不要接单。再比如要实现一个代理的服务器去访问真正提供服务的服务器,代理服务器可能要先判断用户是否合法才去访问真正提供服务的服务器,用户访问的其实是代理的接口,只有用户合法才能够去访问真正接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cfl927096306

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值