代理模式
urrogate or placeholder for another object to control access to it.
(为其他对象提供一种代理以控制对这个对象的访问。)
通用类图
抽象主题类
是一个最普通的业务类型定义
具体主题类
被代理角色;业务逻辑的具体指向者,继承抽象主题类,和代理主题类关联
代理主题类
代理类;负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给具体主题角色实现,同样继承抽象主题类。
通用源码
//抽象主题类
class Subject {
public:
//定义一个方法
virtual void request() = 0;
};
//具体主题类
class RealSubject : public Subject {
public:
//实现方法
virtual void request() {
//业务逻辑处理
}
};
//代理类
class Proxy : public Subject {
private:
//要代理哪个实现类
Subject *msubject = NULL;
//预处理
void before() {
//业务逻辑处理
}
//善后处理
void after() {
//业务逻辑处理
}
public:
//默认被代理者
Proxy() {
msubject = new Proxy();
}
//通过构造函数传递代理者
Proxy(Subject* subject) {
msubject = subject;
}
//实现接口中定义的方法
virtual void request() {
this->before();
msubject->request();
this->after();
}
}
优点
职责清晰,具体的角色就是实际的业务逻辑,不用关心其他非本职责的事务
高扩展性,具体的角色随时都会发生变化,但是只要实现了接口,代理类可以不做任何修改就可以使用
智能化,见扩展中的动态代理
扩展
1普通代理,客户端只能访问代理角色,不能访问具体角色;通过修改具体角色类和代理角色类的构造函数,使得可以通过代理角色类的构造函数直接获得具体角色的对象,从而对具体角色进行封装
2强制代理,要从具体角色查找获得代理角色,不允许直接访问具体角色,也不允许随便new一个代理角色访问。只能通过新增getProxy()方法获得具体角色的代理角色进行访问具体角色
3代理是有个性的,可以实现其他接口完成不同的任务,对目标对象的方法进行拦截和过滤。
4动态代理,是现阶段不用关心代理谁,运行阶段才指定代理哪一个对象。要用到反射机制,c++貌似没有反射机制。
示例代码
#include <iostream>
#include <string>
using namespace std;
class IGamePlayer {
public:
virtual void login(string& user, string& password) = 0;
virtual void killBoss() = 0;
virtual void upgrade() = 0;
};
class GamePlayer : public IGamePlayer {
private:
string mname;
public:
GamePlayer(string name) {mname = name;}
virtual void killBoss() {
cout << mname << " kill Boss!!!" << endl;
}
virtual void login(string& user, string& password) {
cout << "user: " << user <<"\npassword: " << password << endl;
}
virtual void upgrade() {
cout << mname << " upgrade!!!" << endl;
}
};
class GamePlayerProxy : public IGamePlayer {
private:
IGamePlayer* mgamePlayer = NULL;
public:
GamePlayerProxy(IGamePlayer* gamePlayer) {
mgamePlayer = gamePlayer;
}
virtual void killBoss() {
mgamePlayer->killBoss();
}
virtual void login(string& user, string& password) {
mgamePlayer->login(user, password);
}
virtual void upgrade() {
mgamePlayer->upgrade();
}
};
int main() {
IGamePlayer *p = new GamePlayer("zl");
string user("zl"), password("970724");
IGamePlayer *proxy = new GamePlayerProxy(p);
proxy->login(user, password);
proxy->killBoss();
proxy->upgrade();
return 0;
}
强制代理模式
#include <iostream>
#include <string>
using namespace std;
class IGamePlayer {
public:
virtual void login(string& user, string& password) = 0;
virtual void killBoss() = 0;
virtual void upgrade() = 0;
virtual IGamePlayer* getPorxy() = 0;
};
class GamePlayPorxy : public IGamePlayer {
private:
IGamePlayer* mgamePlayer = NULL;
public:
GamePlayPorxy(IGamePlayer* pGamePlayer) {
mgamePlayer = pGamePlayer;
}
virtual void login(string& user, string& password) {
mgamePlayer->login(user, password);
}
virtual void killBoss() {
mgamePlayer->killBoss();
}
virtual void upgrade() {
mgamePlayer->upgrade();
}
virtual IGamePlayer* getPorxy() {
return this;
}
};
class GamePlayer : public IGamePlayer {
private:
string mname;
GamePlayPorxy* mPorxy = NULL;
public:
GamePlayer(string name) {
mname = name;
}
virtual void login(string& user, string& password) {
if(mPorxy) {
cout<<"user: "<<user<<" name: " <<mname<<" login successful!"<<endl;
} else {
cout<<"please use proxy"<<endl;
}
}
virtual void killBoss() {
if(mPorxy) {
cout<<mname<<" kill boss!!!"<<endl;
} else {
cout<<"please use proxy"<<endl;
}
}
virtual void upgrade() {
if(mPorxy) {
cout<<mname<<" upgrade!!!"<<endl;
} else {
cout<<"please use proxy"<<endl;
}
}
virtual IGamePlayer* getPorxy() {
mPorxy = new GamePlayPorxy(this);
return mPorxy;
}
};
int main() {
string user("user"), password("password"), name("zl");
//错误方式,直接访问具体角色
IGamePlayer* pGamePlayer0 = new GamePlayer(name);
pGamePlayer0->login(user, password);
pGamePlayer0->killBoss();
pGamePlayer0->upgrade();
delete pGamePlayer0;
//错误方式,随便new一个proxy
IGamePlayer* pGamePlayer1 = new GamePlayer(name);
IGamePlayer* pPorxy = new GamePlayPorxy(pGamePlayer1);
pPorxy->login(user, password);
pPorxy->killBoss();
pPorxy->upgrade();
delete pGamePlayer1;
delete pPorxy;
//正确方式
IGamePlayer* pGamePlayer2 = new GamePlayer(name);
pGamePlayer2->getPorxy()->login(user, password);
pGamePlayer2->getPorxy()->killBoss();
pGamePlayer2->getPorxy()->upgrade();
delete pGamePlayer2;
return 0;
}