1、 适配器模式
定义:将一个类的接口转换为客户希望的另一个接口,使得原本由于接口不兼容而不能在一起工作的那些类可以一起工作。
例如,我们使用for_each()来遍历数组
class MyPrint {
public:
void operator()(int v1, int v2){
cout << v1 + v2 << endl;
}
};
int main()
{
vector<int> v;
for (int i = 0; i < 10; i++)
v.push_back(i);
for_each(v.begin(), v.end(), MyPrint());
}
这段代码是不能编译的,这是因为for_each中的仿函数直接接受一个参数(这个参数为数组元素),而我们传入了两个参数。
所以我们需要转换接口,将两个元素的仿函数转换为一个元素的仿函数
//本来需要传入的仿函数
class MyPrint {
public:
void operator()(int v1, int v2){
cout << v1 + v2 << endl;
}
};
//要适配成什么样子
class Target {
public:
virtual void operator()(int v) = 0;
};
//定义目标接口,将接收两个参数的仿函数MyPrint转换为一个参数
class Adapter :public Target {
public:
virtual void operator()(int v) {
print(v, 100);
}
public:
MyPrint print;
};
int main()
{
vector<int> v;
for (int i = 0; i < 10; i++)
v.push_back(i);
for_each(v.begin(), v.end(), Adapter());
}
我们发现虽然现在可以编译了,但如果要指定另一个元素,需要更改Adapter,违背了开闭原则,所以我们还可以改进。使其可以进行绑定指定的另一个元素。
所以增加一个bind类
class MyPrint {
public:
void operator()(int v1, int v2){
cout << v1 + v2 << endl;
}
};
//要适配成什么样子
class Target {
public:
virtual void operator()(int v) = 0;
};
//定义目标接口,将接收两个参数的仿函数MyPrint转换为一个参数
class Adapter :public Target {
public:
Adapter(int v) :_para(v)
{}
virtual void operator()(int v) {
print(v, _para);
}
public:
MyPrint print;
int _para;
};
//Mybind
Adapter Mybind(int v)
{
return Adapter(v);
}
int main()
{
vector<int> v;
for (int i = 0; i < 10; i++)
v.push_back(i);
for_each(v.begin(), v.end(), Mybind(10));
}
总结:由于应用环境的变化,常常需要将”一些现存的对象“放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足。
那么如何应对这些”迁移的变化“?将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
2、 代理模式
代理模式定义:为其他对象提供一种代理以控制对这个对象的访问,在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介作用。这里我们假设客户端不能直接访问系统,只能通过代理,在验证密码和身份之后才能访问
//提供一种代理来控制对其他对象的访问
class AbstractCommonInterface {
public:
virtual void run() = 0;
};
//需要访问的系统 -->抽象出系统,满足开闭原则
class MySystem :public AbstractCommonInterface {
public:
virtual void run() {
cout << "系统启动..." << endl;
}
};
//进行代理,验证身份和密码
class MySystemProxy :public AbstractCommonInterface {
public:
MySystemProxy(string name, string password) {
m_name = name;
m_password = password;
pSystem = new MySystem;
}
virtual void run() {
if (check())
{
pSystem->run();
cout << "登录成功"<<endl;
}
else
{
cout << "密码错误" << endl;
}
}
~MySystemProxy()
{
if (pSystem)
delete pSystem;
}
protected:
bool check()
{
if (m_name == "123"&&m_password == "456")
return true;
return false;
}
private:
MySystem* pSystem;
string m_name;
string m_password;
};
void main()
{
MySystemProxy* proxy = new MySystemProxy("123", "458");
proxy->run();
}
3、 装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。是对继承的一种替代。
假设现在有一个英雄,现在这个对象需要进行装饰,穿衣服,随后就变为了穿了衣服的英雄。
//英雄 ---add装饰物
//通过继承实现类的功能的扩展
//抽象英雄
class AbstractHero {
public:
virtual void ShowStatus() = 0;
public:
int mHp;
int mMp;
int mAt;
int mDf;
};
//具体英雄
class HeroA :public AbstractHero
{
public:
HeroA()
{
mHp=0;
mMp=0;
mAt=0;
mDf=0;
}
virtual void ShowStatus()
{
cout << "血量: " << mHp << endl;
cout << "魔法: " << mMp << endl;
cout << "攻击: " << mAt << endl;
cout << "防御: " << mDf << endl;
}
};
//英雄穿上某个装饰物,那么他还是英雄,但不是原来的英雄
class AbstractEquipment :public AbstractHero {
public:
AbstractEquipment(AbstractHero* hero) {
this->pHero = hero;
}
virtual void ShowStatus() {}
public:
AbstractHero* pHero;
};
//狂徒
class KuangTuEquipment :public AbstractEquipment {
public:
KuangTuEquipment(AbstractHero* hero) :AbstractEquipment(hero) {}
//增加额外功能
void AddKuangTu() {
cout << "装备完成...." << endl;
mHp = pHero->mHp+ 80;
mMp = pHero->mMp;
mAt = pHero->mAt;
mDf = pHero->mDf + 20;
delete this->pHero;
}
virtual void ShowStatus() {
AddKuangTu();
cout << "血量: " << mHp << endl;
cout << "魔法: " << mMp << endl;
cout << "攻击: " << mAt << endl;
cout << "防御: " << mDf << endl;
}
};
void test()
{
AbstractHero* hero = new HeroA;
hero->ShowStatus();
cout << "----------" << endl;
//装备狂徒
hero = new KuangTuEquipment(hero);
hero->ShowStatus();
}
int main()
{
test();
}