代理模式属于结构型设计模式,并不关注与对象的产生,而是类和对象功能的使用;
该类模设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。
比如说我们想要访问某公司的老板,其实不可能是直接打到老板那里,而是先打给助理。这里的助理就是代理proxy的角色。
代理模式主要体现的是对于我们对象即老板的权限控制,不是所有的客户都能够访问老板的。
所以代理模式就是通过代理类。来控制实际对象(老板/委托类)的访问权限。
我们先举一个例子来探讨代理模式的好处。
案例
我们拿视频网站来举例,视频网站有免费的、有VIP的、也有必须要买券购买观看权的。
#include <iostream>
using namespace std;
class VideoSite {
public:
virtual ~VideoSite() = default;
virtual void freeMovie() = 0; //免费电影
virtual void vipMovie() = 0; //vip电影
virtual void tickMovie() = 0; //用券观看
};
class FixBugVideoSite : public VideoSite {
public:
void freeMovie() override { //免费电影
cout << "观看免费电影" << endl;
}
void vipMovie() override { //vip电影
cout << "观看vip电影" << endl;
}
void tickMovie() override {//用券观看
cout << "用券观看电影" << endl;
}
};
我们开始看电影:
int main () {
VideoSite *p1 = new FixBugVideoSite();
p1->freeMovie();
p1->vipMovie();
p1->tickMovie();
}
我们直接就可以看各类电影,达不到我们设计的初衷,应该每一类电影都需要有权限设置。
所以我们需要加代理类,代理的就是我们的FixBugVideoSite,不允许客户指针直接指向我们的委托类对象FixBugVideoSite
,而是指向我们的代理类对象,用代理对象来控制客户对委托类访问对象权限的问题。
//代理类,代理的就是我们的FixBugVideoSite
class FreeVideoSiteProxy : public VideoSite {
public:
FreeVideoSiteProxy() { pVideo = new FixBugVideoSite(); }
~FreeVideoSiteProxy() { delete pVideo; }
//通过代理对象的freeMovie来访问真正委托类对象的方法
virtual void freeMovie() { pVideo->freeMovie(); }
virtual void vipMovie() {
cout << "您目前只是普通游客,需要升级成vip才能观看vip电影" << endl;
}
virtual void tickMovie() {
cout << "你目前没有电影券,该电影您需要买券观看" << endl;
}
private:
VideoSite *pVideo;
};
在调用时,也只允许我们的客户指针指向代理类;
#include <memory>
int main () {
unique_ptr<VideoSite> p1(new FreeVideoSiteProxy());
p1->freeMovie();
p1->vipMovie();
p1->tickMovie();
}
/*输出
观看免费电影
您目前只是普通游客,需要升级成vip才能观看vip电影
你目前没有电影券,该电影您需要买券观看
*/
在这里我们只实现了免费客户的代理类,其他级别的代理类可以自行实现。
总结
首先我们需要有
- 公共的抽象类;
class VideoSite {
public:
virtual ~VideoSite() = default;
virtual void freeMovie() = 0; //免费电影
virtual void vipMovie() = 0; //vip电影
virtual void tickMovie() = 0; //用券观看
};
- 委托类。它需要从公共的抽象类继承而来。
class FixBugVideoSite : public VideoSite {
public:
void freeMovie() override { //免费电影
cout << "观看免费电影" << endl;
}
void vipMovie() override { //vip电影
cout << "观看vip电影" << endl;
}
void tickMovie() override {//用券观看
cout << "用券观看电影" << endl;
}
};
- 代理类。
class FreeVideoSiteProxy : public VideoSite {
public:
FreeVideoSiteProxy() { pVideo = new FixBugVideoSite(); }
~FreeVideoSiteProxy() { delete pVideo; }
virtual void freeMovie() { pVideo->freeMovie(); }
virtual void vipMovie() {
cout << "您目前只是普通游客,需要升级成vip才能观看vip电影" << endl;
}
virtual void tickMovie() {
cout << "你目前没有电影券,该电影您需要买券观看" << endl;
}
private:
VideoSite *pVideo;
};
- 以组合的方式来使用我们的代理对象。也就是委托类的成员变量,用来对外提供借口。
private:
VideoSite *pVideo;
private:
FixBugVideoSite Video;//这样写灵活性较差
- 客户直接访问代理对象
unique_ptr<VideoSite> p1(new FreeVideoSiteProxy());