装饰者模式又叫包装模式,把要添加的附加功能分别放在单独的类中,并让这个类包含它要装饰的对象,当需要添加功能时,只需要有选择、按顺序的使用装饰功能来包装对象。
设计模式如下图:
?
一个简单的例子:一辆小汽车,基本功能是可以跑。但是我要对这个汽车增加功能,比如让它可以飞翔,让它可以在水里跑,或者其他功能。当基类的汽车,需要什么功能,我就添加什么功能。把功能设计成类。
设计代码如下:
class car
{
public:
virtual void show() = 0;
};
class RunCar:public car
{
public:
virtual void show()
{
cout << "可以跑"<<endl;
}
};
class SwimCarDirector:public car
{
public:
SwimCarDirector(car* pCar)
{
m_pCar = pCar;
}
void swim()
{
cout << "可以游泳"<<endl;
}
virtual void show()
{
m_pCar->show();
swim();
}
car* m_pCar;
};
class FlyCarDirectory:public car
{
public:
FlyCarDirectory(car *pCar)
{
m_pCar = pCar;
};
void fly()
{
cout << "能飞的车" << endl;
}
virtual void show()
{
m_pCar->show();
fly();
}
private:
car* m_pCar;
};
int main()
{
car* pCar = new RunCar;
pCar->show();
cout << "aaaaa-----"<<endl;
//增加游泳功能
SwimCarDirector* pSwim = new SwimCarDirector(pCar);
pSwim->show();
cout << "bbbb-----"<<endl;
//增加飞行功能
FlyCarDirectory* pFly = new FlyCarDirectory(pSwim);
pFly->show();
cout << "cccc----"<<endl;
}
一个复杂的例子:
星巴克咖啡店要做咖啡,之前类的设计如下:
?如果要买咖啡,还要加入各种调料,那么就要继续添加功能,导致添加各种类,显得非常复杂。
采用装饰者模式,把饮料作为基类,各种咖啡作为子类继承,把调料单独写个子类继承基类,然后。需要添加调料,就创建一个调料类。设计模式如下:
?
示例代码如下:
//饮料基类
class Drink
{
public:
Drink(void){m_sDescription = "unknow drink";};
virtual double cost() = 0;
virtual string getDescription()
{
return m_sDescription;
};
string m_sDescription;
};
//调味品基类 继承饮料
class CDecorator:public Drink
{
public:
virtual double cost() = 0;
virtual string getDescription() = 0;
};
//拿铁
class CEspresso:public Drink
{
public:
CEspresso(){m_sDescription = "Espresso";};
~CEspresso();
virtual double cost()
{
return 1.2;
}
};
//浓缩咖啡
class CNSCoffe:public Drink
{
public:
CNSCoffe(){m_sDescription = "CNSCoffe";};
~CNSCoffe();
virtual double cost()
{
return 1.0;
}
};
//调料1
class Slat:public CDecorator
{
public:
Slat(Drink* pDrink):m_pDrink(pDrink)
{
};
~Slat();
virtual string getDescription()
{
return (m_pDrink->getDescription() + ",Slat");
};
virtual double cost()
{
return (0.2 + m_pDrink->cost());
};
private:
Drink* m_pDrink;
};
//调料2
class Suguar:public CDecorator
{
public:
Suguar(Drink* pDrink):m_pDrink(pDrink)
{
};
~Suguar();
virtual string getDescription()
{
return (m_pDrink->getDescription() + ",Suguar");
};
virtual double cost()
{
return (0.8 + m_pDrink->cost());
};
private:
Drink* m_pDrink;
};
int main()
{
//我想喝一杯简单的咖啡
Drink* pDrink = new CNSCoffe;
cout << pDrink->getDescription()<<": $" << pDrink->cost() << endl;
//喝一杯拿铁 加两盐一糖
Drink* pDrink2 = new CEspresso;
Slat* pCon1 = new Slat(pDrink2);
Slat* pCon2 = new Slat(pCon1);
Suguar* pCon3 = new Suguar(pCon2);
cout << pCon3->getDescription()<<":$";
cout << pCon3->cost() << endl;
}
输出结果为:
CNSCoffe: $1
Espresso Slat,Slat,Suguar: $2.4
?
|