1 代理模式
代理模式的通俗理解为,一个人(代理人)替另一个 (被代理人)来做某些事情。
代理模式(Proxy):为其它对象提供一种代理以控制对这个对象的访问。
代理模式的类图如下:
背景:书中小故事,卓贾易同学送想要追求娇娇,但不认识娇娇,就找戴励同学帮其送礼物给娇娇,结果最后代理人戴励与娇娇在一起了,卓贾易成了为别人做嫁衣。 题目:写代码来表示上述送礼物功能
版本一:没有代理,让追求者卓贾易直接送礼物给追求娇娇,类图如下:
这里需要实现两个类:
// 被追求者
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;
};
首先实例化一个被追求者,
然后实例化一个追求者,并传入被追求者,然后依次调用追求者的送礼物接口。
#include <iostream>
int main()
{
// 被追求者
SchoolGirl jiaojiao;
jiaojiao.name = "娇娇";
// 追求者
Pursuit zhuojiayi = Pursuit(jiaojiao); // 娇娇并不认识卓贾易,此处有问题
zhuojiayi.GiveDOlls();
zhuojiayi.GiveFlowers();
zhuojiayi.GiveChocolate();
return 0;
}
代码运行效果如下:
由于实际情况是,娇娇并不认识卓贾易,因此不能直接将被追求者作为参数传递给给追求者。
下面来看版本二,使用代理,因为代理者认识娇娇。
版本二与版本一的结构基本一致,只是将追求者换成了代理人,类图如下:
这里需要实现两个类:
// 被追求者
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;
};
首先实例化一个被追求者,
然后实例化一个代理者,并传入被追求者,然后依次调用追求者的送礼物接口。
#include <iostream>
int main()
{
// 被追求者
SchoolGirl jiaojiao;
jiaojiao.name = "娇娇";
// 代理人
Proxy daili = Proxy(jiaojiao); // 此时是代理者“戴励”,追求者实例“卓贾易”又不在了
daili.GiveDOlls();
daili.GiveFlowers();
daili.GiveChocolate();
return 0;
}
代码运行效果如下:
版本二这种写法,完全忽视了被代理者(追求者,卓贾易)的存在,也是不合实际的。
实际需求是要能体现礼物是追求者买的,代理是帮忙送礼物。
版本三使用代理模式,类图如下,定义一个接口类,来声明需要代理来送的礼物类型,
然后追求者类(被代理人,卓贾易)和代理人类(戴励)各自实现送礼物的具体接口,实现接口,用虚线+空心三角表示,
代理人的接口内部,实际是调用被代理人的接口实现,
这里代理人需要“知道”被代理人的各种代理需求,这种“知道”的关系属于关联关系,用实线(加箭头)表示。
这里需要实现四个类:
// 被追求者
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;
};
#include <iostream>
int main()
{
SchoolGirl *jiaojiao = new SchoolGirl();
jiaojiao->name = "娇娇";
Proxy daili = Proxy(jiaojiao);
daili.GiveDolls();
daili.GiveFlowers();
daili.GiveChocolate();
delete jiaojiao;
return 0;
}
代码运行效果如下: