学习软件设计,向OO高手迈进!
设计模式(Design pattern)是软件开发人员在软件开发过程中面临的一般问题的解决方案。
这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
是前辈大神们留下的软件设计的"招式"或是"套路"。
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式,也就是说当客户端无法直接访问某个对象或访问某个对象存在困难时,可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口。
举例说明,就是一个人或者一个机构,代表另一个人或者另一个机构采取行动。在一些情况下,客户端不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用。
在代理模式中,我们为其他对象提供一种代理以控制对这个真实对象的访问。
直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的间接层,**“增加一层间接层”**是软件系统中对许多复杂问题的一种常见解决方法。
代理模式中的角色:
下面我们以送女朋友礼物来讲解该模式:
比如说你把你女朋友给惹毛了,这时候你直接去求原谅可能她不会鸟你。这怎么办?拿出手机,打开美
团跑腿,叫个外卖小哥给她送点礼物消消气,方便后面的行动。在这个例子中,你自己就是真实角色,外卖小哥就是代理你的角色,由他来代表你去送礼物,这就是代理的意思。
一、定义抽象主题类
// 抽象主题类(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
从上面的示例和UML图看,先访问代理类再访问真正要访问的对象。似乎这样有点多此一举的味道,其实不然,这是有一定道理的。
代理类可以在真正的类执行之前,进行一些预处理。比如上面的示例中,外卖小哥看到有订单后,先判断一下要送到哪里,和自己当前位置远不远,要不要绕路等,然后再决定要不要接单。再比如要实现一个代理的服务器去访问真正提供服务的服务器,代理服务器可能要先判断用户是否合法才去访问真正提供服务的服务器,用户访问的其实是代理的接口,只有用户合法才能够去访问真正接口。