加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • 1 代理模式
    • 2 实例
    • 总结
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

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

06/24 12:30
561
阅读需 11 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

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

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

1 代理模式

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

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

代理模式的类图如下:

    • Subject:抽象主题类,

定义了需要代理的接口

    • RealSubject:具体主题类,即被代理类,

实现具体的接口功能

    • Proxy:代理类,提供代理接口,其具体的功能实现是调用被代理人的接口功能,即

作为中间人来替别人和第三方进行交互

2 实例

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

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

2.1 版本一:没有代理

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

2.1.1 追求者与被追求者类

这里需要实现两个类:

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

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

// 被追求者
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 主函数

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

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

#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 代理者与被追求者类

这里需要实现两个类:

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

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

// 被追求者
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 主函数

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

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

#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,声明需要代理的功能

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

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

// 被追求者
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 主函数

#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++编程,来演示代理模式的使用。

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
ECS-3225S18-250-FN-TR 1 ECS International Inc CMOS Output Clock Oscillator,
暂无数据 查看
LTC2875HS8#PBF 1 Linear Technology LTC2875 - ±60V Fault Protected 3.3V or 5V 25kV ESD High Speed CAN Transceiver; Package: SO; Pins: 8; Temperature Range: -40&deg;C to 125&deg;C
$3.57 查看
FOD420SDV 1 Fairchild Semiconductor Corporation Triac Output Optocoupler, 1-Element, 5000V Isolation, LEAD FREE, SURFACE MOUNT PACKAGE-6
$4.23 查看

相关推荐

电子产业图谱

控制科学与工程硕士,日常分享单片机、嵌入式、C/C++、Linux等学习经验干货~