文章目录
本文是结构型模式的第二部分,如果读者对结构型模式感兴趣,可以先阅读第一部分。
1.装饰(Decorator)模式
装饰模式(Decorator Pattern):动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。在现实生活中,常常需要对心有产品增加新的功能或美化其外观,如房子装修、相片加相框等。在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下,可以动态地扩展其功能。所有这些都可以釆用装饰模式来实现。
Component(抽象构件):它是 具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
ConcreteComponent(具体构件):它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
Decorator(抽象装饰类):它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。
#include <iostream>
#include <string>
using namespace std;
// Component(抽象构件),它是具体构件和抽象装饰类的共同父类,手机
class Phone
{
public:
virtual void show() = 0;
};
// ConcreateComponent(具体构件),iphone
class Iphone : public Phone
{
public:
Iphone(string kind)
{
this->kind = kind;
}
virtual void show()
{
cout << "我掏出了 iphone-" << kind << "秀了秀" << endl;
}
private:
string kind;
};
// ConcreateComponent(具体构件),小米手机
class MiPhone : public Phone
{
public:
MiPhone(string kind)
{
this->kind = kind;
}
virtual void show()
{
cout << "我掏出了 小米-" << kind << "秀了秀" << endl;
}
private:
string kind;
};
// Decorator(抽象装饰类),手机装饰器
class DecoratorPhone : public Phone
{
public:
DecoratorPhone()
{
}
DecoratorPhone(Phone* phone)
{
this->phone = phone;
}
virtual void show()
{
this->phone->show();
}
private:
Phone* phone;
};
// ConcreteDecorator(具体装饰类),贴膜装饰器
class DecoratorPhoneMo : public DecoratorPhone
{
public:
DecoratorPhoneMo(Phone* phone)
{
this->phone = phone;
}
void AddMo()
{
cout << "装饰:手机贴膜" << endl;
}
virtual void show()
{
this->phone->show();
AddMo();
}
private:
Phone* phone;
};
// ConcreteDecorator(具体装饰类),皮套装饰器
class DecoratorPhoneTao : public DecoratorPhone
{
public:
DecoratorPhoneTao(Phone* phone)
{
this->phone = phone;
}
void AddTao()
{
cout << "装饰:手机外套" << endl;
}
virtual void show()
{
this->phone->show();
AddTao();
}
private:
Phone* phone;
};
int main(void)
{
Phone *phone = NULL;
DecoratorPhone* hasMoPhone = NULL;
DecoratorPhone* hasTaoPhone = NULL;
DecoratorPhone* hasMoTaoPhone = NULL;
// 定义一个 iphone12
phone = new Iphone("12");
// 给 iphone12 贴膜
hasMoPhone = new DecoratorPhoneMo(phone);
// 给 iphone12 加上皮套
hasTaoPhone = new DecoratorPhoneTao(phone);
hasMoPhone->show();
hasTaoPhone->show();
// 给有皮套的 iphone12 再贴膜
hasMoTaoPhone = new DecoratorPhoneMo(hasTaoPhone);
hasMoTaoPhone->show();
delete hasMoPhone;
delete hasTaoPhone;
delete hasMoTaoPhone;
delete phone;
return 0;
}
2.外观模式
外观模式就是将复杂的子类系统(SubSystem)抽象到同一个接口(Façade)进行管理,外界只需要通过此接口(Façade)与子类系统(SubSystem)进行交互,而不需要直接与复杂的子类系统(SubSystem)进行交互。
#include <iostream>
using namespace std;
class TV
{
public:
void On()
{
cout << "电视打开了" << endl;
}
void Off()
{
cout << "电视关闭了" << endl;
}
};
class DVD
{
public:
void On()
{
cout << "DVD打开了" << endl;
}
void Off()
{
cout << "DVD关闭了" << endl;
}
};
class Xbox
{
public:
void On()
{
cout << "Xbox打开了" << endl;
}
void Off()
{
cout << "Xbox关闭了" << endl;
}
};
class MikePhone
{
public:
void On()
{
cout << "MikePhone打开了" << endl;
}
void Off()
{
cout << "MikePhone关闭了" << endl;
}
};
class Light
{
public:
void On()
{
cout << "Light打开了" << endl;
}
void Off()
{
cout << "Light关闭了" << endl;
}
};
class HomePlayer
{
public:
//ktv模式的接口
void doKTV()
{
light.Off();
tv.On();
dvd.On();
}
//游戏模式的接口
void doGame()
{
tv.On();
xbox.On();
}
Light light;
TV tv;
MikePhone mike;
Xbox xbox;
DVD dvd;
};
int main(void)
{
HomePlayer hp;
cout << "进入ktv模式" << endl;
hp.doKTV();
cout << "进入游戏模式" << endl;
hp.doGame();
return 0;
}
(1)它对客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易。 通过引入外观模式,客户端代码将变得很简单,与之关联的对象也很少 。
(2)它实现了子系统与客户端之间的松耦合关系,这使得子系统的变化不会影响到调用它的客户端,只需要调整外观类即可。
(3)一个子系统的修改对其他子系统没有任何影响。
3.享元模式
享元模式是为了应对大量细粒度对象重复的问题。程序中存在大量细粒度的对象,每次要使用时都必须创建一个新的对象,既影响了运行效率又增加了内存消耗。于是有了享元模式,享元模式提取出这些细粒度对象中间公共的状态(属性,我的理解),只生成一个实例对象,所有用到这些公共属性对象的地方,都指向这一个实例。
//Flyweight
class tool
{
public:
//内蕴状态
string name;
int nSize;
int nWeight;
public:
//外蕴状态
virtual int used(string person, string work)=0;
}
//ConcreteFlyweight
class hammer : public tool
{
public:
hammer():name("hammer"){}
int used(string person, string work)
{
cout<< person <<"use"<<name<<"to" << work;
}
}
//ConcreteFlyweight
class screwdriver : public tool
{
screwdriver():name("screwdriver"){}
int used(string person, string work)
{
cout<< person <<"use"<< name << " to" << work;
}
}
//ConcreteFlyweight
class saw : public tool
{
saw():name("saw"){}
int used(string person, string work)
{
cout<< person <<"use"<< name <<"to" << work;
}
}
//FlyweightFactory
class toolbox
{
public:
toolbox();
virtual ~toolbox()
{
map<string,tool*>::iterator it = m_tool.find(toolname);
for(it=m_tool.begin();it!=m_tool.end();it++)
{
delete it.second;
}
}
tool* GetTool(string toolname)
{
map<string,tool*>::iterator it = m_tool.find(toolname);
if(it != m_tool.end())
{
return (tool*) it.second;
}
else
{
tool* tooltemp= NULL;
if(toolname == "hammer")
tooltemp = new hammer();
else if(toolname == "screwdriver")
tooltemp = new screwdriver();
else if(toolname == "saw")
tooltemp = new saw();
if(tooltemp !=NULL)
m_tool.insert(make_pair<string,tool*>(toolname,tooltemp));
return tooltemp;
}
}
private:
map<string,tool*> m_tool;
}
int main()
{
//外蕴状态 由调用者维护
string person1 = "zhangsan";
string person2 = "lisi";
string work1 = "make desk";
string work2 = "repair bike";
//生成工厂
toolbox tBox;
//获取享元
tool* tool1 = tBox.GetTool("hammer");
tool1.used(person1,work1);
tool* tool2 = tBox.GetTool("screwdriver");
tool2.used(person2,work2);
}
4.作者答疑
如有疑问,请留言。