代理模式是一种构造型设计模式,通过代理类可以在对具体的业务类进行访问上做一些具体的控制,扩展;也可以做到延迟具体类的实例化。通过代理模式可以在原有业务逻辑外增加一定的约束,比如排序、范围限制等等,无论具体类还是代理类都实现抽象主题。
- Subject抽象主题角色
抽象主题类可以是抽象类也可以是接口, 是一个最普通的业务类型定义, 无特殊要求。 - RealSubject具体主题角色
也叫做被委托角色、 被代理角色。业务逻辑的具体执行者。 - Proxy代理主题角色
也叫做委托类、 代理类。 它负责对真实角色的应用, 把所有抽象主题类定义的方法限制委托给真实主题角色实现, 并且在真实主题角色处理完毕前后做预处理和善后处理工作。
优点: 职责清晰;高扩展性;智能化
缺点:引入了另一个抽象层;影响速度
理解:a中包含b类,a、b类实现协议类protocol。
场景:为其它对象提供一种代理以控制对这个对象的访问
代理模式的实现步骤:
1.提供一个抽象主题角色:真实主题与代理主题的共同接口;
2.提供一个真实主题角色:定义了代理角色所代表的真实对象;
3.提供一个代理主题角色:含有对真实主题角色的引用。
下面是代理模式的一个例子,进行账号登录时,通过代理类判断用户是否存在和密码是否正确,再调用具体的类对象。这样具体的类只需关注自己的业务逻辑即可,其他账号密码等操作或权限可以通过代理类分离出去。
#ifndef SUBJECTPROXY_H
#define SUBJECTPROXY_H
#include "iostream"
#include "cstring"
using namespace std;
class Subject
{
public:
virtual ~Subject(){}
virtual void Request(string id, string pwd)=0;
};
#endif
#ifndef REALSUBJECT_H
#define REALSUBJECT_H
#include "SubjectProxy.h"
class RealSubject : public Subject
{
public:
virtual void Request(string id, string pwd)
{
cout << id << ": " << pwd << " login ok" << endl;
}
};
#endif
#ifndef PROXY_H
#define PROXY_H
#include "RealSubject.h"
#include <unordered_map>
class Proxy : public Subject
{
public:
bool addUsr(string id, string pwd)
{
auto it = m_usrmap.find(id);
if(it != m_usrmap.end())
{
cout << "usr exit " << it->first << ": " << it->second << endl;
return false;
}
m_usrmap.insert(make_pair(id,pwd));
return true;
}
void eraseUsr(string id)
{
m_usrmap.erase(id);
}
void showALLUsr()
{
auto it = m_usrmap.begin();
while(it != m_usrmap.end())
{
cout << it->first << ": " << it->second << endl;
++it;
}
}
bool preRequest(string id, string pwd)
{
auto it = m_usrmap.find(id);
if(it == m_usrmap.end())
{
cout << "usr not exit " << endl;
return false;
}
if(strcmp(it->second.c_str(), pwd.c_str()) != 0)
{
cout << "pwd error" << endl;
return false;
}
return true;
}
virtual void Request(string id, string pwd)
{
if(!preRequest(id,pwd))
{
cout << id << " login fail" << endl;
return;
}
m_realsubject = new RealSubject;
m_realsubject->Request(id,pwd);
delete m_realsubject;
cout << id << " login ok" << endl;
}
private:
unordered_map<string,string> m_usrmap;
RealSubject *m_realsubject;
};
#endif
Proxy *proxy = new Proxy;
proxy->addUsr("0","111");
proxy->addUsr("1","222");
proxy->showALLUsr();
proxy->Request("0","111");
proxy->Request("1","111");
proxy->Request("1","222");
proxy->eraseUsr("0");
proxy->Request("0","111");