C++设计模式(二)(摘录)
装饰模式
装饰模式:动态地给一个对象添加一些额外的功能,它是通过创建一个包装对象,也就是装饰来包裹真实的对象。新增加功能来说,装饰器模式比生产子类更加灵活。
以下情形考虑使用装饰模式:
需要扩展一个类的功能,或给一个类添加附加职责。
需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的
子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
和建造者模式的区别:
建造者模式要求建造的过程必须是稳定的,而装饰模式的建造过程是不稳定的,可以有各种各样的组合方式。
实例:
1.角色
(1)Component是定义一个对象,可以给这些对象动态地添加职责。
(2)ConcreteComponent是定义了一个具体的对象,也可以给这个对象增加一些职责。
(3)Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但是对于Component来说,是无需知道Decorator的存在的。
(4)至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的作用。
2.C++实现
(1)Conponent即ConcreteComponent类:此处为Person类
#ifndef PERSON_H
#define PERSON_H
#include <string>
#include <iostream>
//ConcreteComponent即Component
class Person
{
private:
std::string name;
public:
Person(){};
Person(std::string name)
{
this->name=name;
}
virtual void Show()
{
std::cout<<"装饰的"<<name<<std::endl;
}
};
#endif
(2)Decorator及ConcreteDecorator:此处为Finery及其子类
#ifndef FINERY_H
#define FINERY_H
#include <iostream>
#include "Person.h"
//Decorator类
class Finery:public Person
{
protected:
Person* component;
public:
void Decorator(Person* component)
{
this->component=component;
}
void Show()
{
if(component!=NULL)
component->Show();
}
};
//下面是一系列ConcreteDecorator类
class TShirts:public Finery
{
public:
void Show()
{
std::cout<<"大T恤 ";
Finery::Show();
}
};
//ConcreteDecorator类
class BigTrouser:public Finery
{
public:
void Show()
{
std::cout<<"垮裤 ";
Finery::Show();
}
};
//ConcreteDecorator类
class Sneakers:public Finery
{
public:
void Show()
{
std::cout<<"破球鞋 ";
Finery::Show();
}
};
//ConcreteDecorator类
class Suit:public Finery
{
public:
void Show()
{
std::cout<<"西装 ";
Finery::Show();
}
};
//ConcreteDecorator类
class Tie:public Finery
{
public:
void Show()
{
std::cout<<"领带 ";
Finery::Show();
}
};
//ConcreteDecorator类
class LeatherShoes:public Finery
{
public:
void Show()
{
std::cout<<"皮鞋 ";
Finery::Show();
}
};
#endif
(3)客户端:main
#include "Finery.h"
#include <string>
#include <iostream>
//客户端
void main()
{
Person* xc=NULL;
xc=new Person("小菜");
std::cout<<"第一种装扮:"<<std::endl;
Sneakers* pqx=NULL;
pqx=new Sneakers();
BigTrouser* kk=NULL;
kk=new BigTrouser();
TShirts* dtx=NULL;
dtx=new TShirts();
pqx->Decorator(xc);
kk->Decorator(pqx);
dtx->Decorator(kk);
dtx->Show();
std::cout<<"第二种装扮:"<<std::endl;
LeatherShoes* px=NULL;
px=new LeatherShoes();
Tie* ld=NULL;
ld=new Tie();
Suit* xz=NULL;
xz=new Suit();
px->Decorator(xc);
ld->Decorator(px);
xz->Decorator(ld);
xz->Show();
if(xc!=NULL)
{
delete xc;
xc=NULL;
}
if(pqx!=NULL)
{
delete pqx;
pqx=NULL;
}
if(kk!=NULL)
{
delete kk;
kk=NULL;
}
if(dtx!=NULL)
{
delete dtx;
dtx=NULL;
}
if(px!=NULL)
{
delete px;
px=NULL;
}
if(ld!=NULL)
{
delete ld;
ld=NULL;
}
if(xz!=NULL)
{
delete xz;
xz=NULL;
}
system("pause");
}
代理模式
代理模式:为其它对象提供一种代理以控制这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介作用。
优点:
职责清晰。真实的角色只负责实现实际的业务逻辑,不用关心其它非本职责的事务,通过后期的代理完成具体的
任务。这样代码会简洁清晰。
代理对象可以在客户端和目标对象之间起到中介的作用,这样就保护了目标对象。
扩展性好。
实现:
/*
* 关键代码:一个是真正的你要访问的对象(目标类),一个是代理对象,真正对象与代理对象实现同一个接口,
* 先访问代理类再访问真正要访问的对象。
*/
#include <iostream>
using namespace std;
class Gril
{
public:
Gril(const string& name = "gril"):m_string(name){}
string getName()
{
return m_string;
}
private:
string m_string;
};
class Profession
{
public:
virtual ~Profession(){}
virtual void profess() = 0;
};
class YoungMan : public Profession
{
public:
YoungMan(const Gril& gril):m_gril(gril){}
void profess()
{
cout << "Young man love " << m_gril.getName().data() << endl;
}
private:
Gril m_gril;
};
class ManProxy : public Profession
{
public:
ManProxy(const Gril& gril):m_pMan(new YoungMan(gril)){}
~ManProxy()
{
delete m_pMan;
m_pMan = nullptr;
}
void profess()
{
m_pMan->profess();
}
private:
YoungMan* m_pMan;
};
int main(int argc, char *argv[])
{
Gril gril("heihei");
ManProxy* proxy = new ManProxy(gril);
proxy->profess();
delete proxy;
proxy = nullptr;
return 0;
}
桥接模式
桥接模式:将抽象部分与实现部分分离,使它们都可以独立变换。
以下情形考虑使用桥接模式:
当一个对象有多个变化因素的时候,考虑依赖于抽象的实现,而不是具体的实现。
当多个变化因素在多个对象间共享时,考虑将这部分变化的部分抽象出来再聚合/合成进来。
当一个对象的多个变化因素可以动态变化的时候。
优点:
将实现抽离出来,再实现抽象,使得对象的具体实现依赖于抽象,满足了依赖倒转原则。
更好的可扩展性。
可动态的切换实现。桥接模式实现了抽象和实现的分离,在实现桥接模式时,就可以实现动态的选择具体的实现。
/*
* 关键代码:将现实独立出来,抽象类依赖现实类。
* 以下示例中,将各类App、各类手机独立开来,实现各种App和各种手机的自由桥接。
*/
#include <iostream>
using namespace std;
//抽象App类,提供接口
class App
{
public:
virtual ~App(){ cout << "~App()" << endl; }
virtual void run() = 0;
};
//具体的App实现类
class GameApp:public App
{
public:
void run()
{
cout << "GameApp Running" << endl;
}
};
//具体的App实现类
class TranslateApp:public App
{
public:
void run()
{
cout << "TranslateApp Running" << endl;
}
};
//抽象手机类,提供接口
class MobilePhone
{
public:
virtual ~MobilePhone(){ cout << "~MobilePhone()" << endl;}
virtual void appRun(App* app) = 0; //实现App与手机的桥接
};
//具体的手机实现类
class XiaoMi:public MobilePhone
{
public:
void appRun(App* app)
{
cout << "XiaoMi: ";
app->run();
}
};
//具体的手机实现类
class HuaWei:public MobilePhone
{
public:
void appRun(App* app)
{
cout << "HuaWei: ";
app->run();
}
};
int main()
{
App* gameApp = new GameApp;
App* translateApp = new TranslateApp;
MobilePhone* mi = new XiaoMi;
MobilePhone* hua = new HuaWei;
mi->appRun(gameApp);
mi->appRun(translateApp);
hua->appRun(gameApp);
hua->appRun(translateApp);
delete hua;
hua = nullptr;
delete mi;
mi = nullptr;
delete gameApp;
gameApp = nullptr;
delete translateApp;
translateApp = nullptr;
return 0;
}