大话设计模式解读04-代理模式

上篇文章,介绍了《大话设计模式》的第6章------装饰模式。

本篇,来介绍《大话设计模式》的第7章------代理模式。并通过C++代码实现实例代码的功能。

1 代理模式

代理模式的通俗理解为,一个人(代理人)替另一个 (被代理人)来做某些事情。

代理模式(Proxy):为其它对象提供一种代理以控制对这个对象的访问。

代理模式的类图如下:

  • Subject:抽象主题类,定义了需要代理的接口
  • RealSubject:具体主题类,即被代理类,实现具体的接口功能
  • Proxy:代理类,提供代理接口,其具体的功能实现是调用被代理人的接口功能,即作为中间人来替别人和第三方进行交互

2 实例

背景:书中小故事,卓贾易同学送想要追求娇娇,但不认识娇娇,就找戴励同学帮其送礼物给娇娇,结果最后代理人戴励与娇娇在一起了,卓贾易成了为别人做嫁衣。

题目:写代码来表示上述送礼物功能

2.1 版本一:没有代理

版本一:没有代理,让追求者卓贾易直接送礼物给追求娇娇,类图如下:

2.1.1 追求者与被追求者类

这里需要实现两个类:

  • 被追求者类,娇娇,目前题目中不需要有其它功能,仅维护一个自己的名字即可

  • 追求者类,卓贾易,在实例化时,传入要追求的对象,并提供送礼物的接口,就是加句打印

c++ 复制代码
// 被追求者
class SchoolGirl
{
public:
    std::string name;
};

// 追求者
class Pursuit
{
public:
    Pursuit(SchoolGirl mm)
    {
        m_mm = mm;
    }
    
    void GiveDOlls()
    {
        printf("%s 送你洋娃娃\n", m_mm.name.c_str());
    }
    
    void GiveFlowers()
    {
        printf("%s 送你鲜花\n", m_mm.name.c_str());
    }    
    
    void GiveChocolate()
    {
        printf("%s 送你巧克力\n", m_mm.name.c_str());
    }  
             
private:
    SchoolGirl m_mm;
};

2.1.2 主函数

首先实例化一个被追求者,

然后实例化一个追求者,并传入被追求者,然后依次调用追求者的送礼物接口。

c++ 复制代码
#include <iostream>

int main()
{
   	// 被追求者
    SchoolGirl jiaojiao;
    jiaojiao.name = "娇娇";
    
    // 追求者
    Pursuit zhuojiayi = Pursuit(jiaojiao); // 娇娇并不认识卓贾易,此处有问题
    zhuojiayi.GiveDOlls();
    zhuojiayi.GiveFlowers();
    zhuojiayi.GiveChocolate();
    
    return 0;
}

代码运行效果如下:

由于实际情况是,娇娇并不认识卓贾易,因此不能直接将被追求者作为参数传递给给追求者。

下面来看版本二,使用代理,因为代理者认识娇娇。

2.2 版本二:只有代理

版本二与版本一的结构基本一致,只是将追求者换成了代理人,类图如下:

2.2.1 代理者与被追求者类

这里需要实现两个类:

  • 被追求者类,娇娇,仅维护一个自己的名字即可

  • 代理者类,戴励,在实例化时,传入要追求的对象,并提供送礼物的接口

c++ 复制代码
// 被追求者
class SchoolGirl
{
public:
    std::string name;
};

// 代理者
class Proxy
{
public:
    Proxy(SchoolGirl mm)
    {
        m_mm = mm;
    }
    
    void GiveDOlls()
    {
        printf("%s 送你洋娃娃\n", m_mm.name.c_str());
    }
    
    void GiveFlowers()
    {
        printf("%s 送你鲜花\n", m_mm.name.c_str());
    }    
    
    void GiveChocolate()
    {
        printf("%s 送你巧克力\n", m_mm.name.c_str());
    }  
             
private:
    SchoolGirl m_mm;
};

2.2.2 主函数

首先实例化一个被追求者,

然后实例化一个代理者,并传入被追求者,然后依次调用追求者的送礼物接口。

c++ 复制代码
#include <iostream>

int main()
{
    // 被追求者
    SchoolGirl jiaojiao;
    jiaojiao.name = "娇娇";
    
    // 代理人
    Proxy daili = Proxy(jiaojiao); // 此时是代理者"戴励",追求者实例"卓贾易"又不在了
    daili.GiveDOlls();
    daili.GiveFlowers();
    daili.GiveChocolate();
    
    return 0;
}

代码运行效果如下:

版本二这种写法,完全忽视了被代理者(追求者,卓贾易)的存在,也是不合实际的。

实际需求是要能体现礼物是追求者买的,代理是帮忙送礼物。

2.3 版本三:符合实际的代码

版本三使用代理模式,类图如下,定义一个接口类,来声明需要代理来送的礼物类型,

然后追求者类(被代理人,卓贾易)和代理人类(戴励)各自实现送礼物的具体接口,实现接口 ,用虚线+空心三角表示,

代理人的接口内部,实际是调用被代理人的接口实现,

这里代理人需要"知道"被代理人的各种代理需求,这种"知道"的关系属于关联关系,用**实线(加箭头)**表示。

2.3.1 追求者、代理者与被追求者类

这里需要实现四个类:

  • 被追求者类,娇娇,仅维护一个自己的名字即可

  • 代理接口,IGiveGift,声明需要代理的功能

  • 追求者类,卓贾易,在(通过代理)实例化时,传入要追求的对象,并提供送礼物的接口,就是加句打印

  • 代理者类,戴励,在实例化时,传入要追求的对象,并提供送礼物的接口,其接口内部是调用追求者类的具体实现

c++ 复制代码
// 被追求者
class SchoolGirl
{
public:
    std::string name;
};

// 代理接口
class IGiveGift
{
public:
    virtual void GiveDolls(){};
    virtual void GiveFlowers(){};
    virtual void GiveChocolate(){};
};

// 追求者
class Pursuit : public IGiveGift
{
public:
    Pursuit(SchoolGirl *mm)
    {
        m_mm = mm;
    }
    
    ~Pursuit()
    {
        if(m_mm)
        {
            delete m_mm;
        }
    }
    
    void GiveDolls()
    {
        printf("%s 送你洋娃娃\n", m_mm->name.c_str());
    }
    
    void GiveFlowers()
    {
        printf("%s 送你鲜花\n", m_mm->name.c_str());
    }    
    
    void GiveChocolate()
    {
        printf("%s 送你巧克力\n", m_mm->name.c_str());
    }  
             
private:
    SchoolGirl *m_mm;
};

// 代理者
class Proxy : public IGiveGift
{
public:
    Proxy(SchoolGirl *mm)
    {
        m_gg = new Pursuit(mm);
    }
    
    ~Proxy()
    {
        if(m_gg)
        {
            delete m_gg;
        }
    }
    
    void GiveDolls()
    {
        m_gg->GiveDolls();
    }
    
    void GiveFlowers()
    {
        m_gg->GiveFlowers();
    }    
    
    void GiveChocolate()
    {
        m_gg->GiveChocolate();
    }  
             
private:
    Pursuit *m_gg;
};

2.3.2 主函数

c++ 复制代码
#include <iostream>

int main()
{
    SchoolGirl *jiaojiao = new SchoolGirl();
    jiaojiao->name = "娇娇";
    
    Proxy daili = Proxy(jiaojiao);
    daili.GiveDolls();
    daili.GiveFlowers();
    daili.GiveChocolate();
    
    delete jiaojiao;
    return 0;
}

代码运行效果如下:

总结

本篇介绍了设计模式中的代理模式,并通过代理人替被代理人送礼物的实例,使用C++编程,来演示代理模式的使用。

相关推荐
晨米酱11 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机16 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机17 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机17 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机17 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤17 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机2 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机2 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴2 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤2 天前
工厂模式
设计模式