装饰模式是结构型设计模式之一,使用一种对客户透明的方式来动态拓展对象的功能,Java IO中各种流的嵌套就是装饰模式的很好体现。
1. 装饰模式介绍
装饰模式定义:
动态地给一个对象添加一些额外的功能,比生成子类要灵活。
装饰模式的使用场景:
需要透明且动态地拓展类的功能的场景。
装饰模式包括的角色:
(1)抽象组件Component类。
(2)组件具体实现ConcreteComponent类。也是被装饰的对象。
(3)抽象装饰类Decorator,内部持有一个组件对象的引用,职责就是装饰ConcreteComponent类。之所以是抽象的,就是为了方便不同的装饰“风格”子类的自定义实现。
(4)具体装饰类ConcreteDecorator。
2 装饰模式实例介绍
咖啡馆订单系统项目,往基础品种中加入牛奶,巧克力等等,就组成了类似巧克力味咖啡,摩卡,卡夫奇诺等等。我们一般在咖啡厅一般都是直接点卡夫奇诺,其价格就是有单品咖啡和各种调料相加在一起的价格。这些所加的配料就是为了装饰咖啡
抽象组件Component类就可以是抽象类Coffee,而ConcreteComponent类就可以是具体的一个人CommonCoffee(普通黑咖啡),也是要被装饰的对象。抽象装饰类Decorator持有了CommonCoffee的引用,并且回调了CommonCoffee本身的一个“普通咖啡”的价格,并且在具体的装饰类中,即“加牛奶和糖”两个类中,分别为主人公CommonCoffee穿上了牛奶和糖,为对象增加了额外的功能。代码也比较简单,如下所示。
class Coffee
{
public:
Coffee(){};
//virtual int getPrice(int) = 0;
//virtual string getName(string) = 0;
virtual void show() = 0;
};
class CommonCoffee :public Coffee
{
private:
int price;
string name;
public:
CommonCoffee(int m_price, string m_name)
{
this->price = m_price;
this->name = m_name;
}
void show()
{
cout << "价格: " << price << endl;
cout<< "名字 " << name << endl;
}
};
class DecoratorCoffee:public Coffee
{
private:
Coffee* blackCoffee;
public:
DecoratorCoffee(){};
DecoratorCoffee(Coffee *m_pCoffee)
{
this->blackCoffee = m_pCoffee;
}
void show()
{
blackCoffee->show();
}
};
class MilkCoffee :public DecoratorCoffee
{
public:
MilkCoffee(){};
MilkCoffee(Coffee*m_pCoffee)
{
this->decoratorCoffee = m_pCoffee;
}
virtual void show()
{
decoratorCoffee->show();
addMilk();
}
void addMilk()
{
cout << "增加牛奶,价格增加1元" << endl;
}
private:
Coffee*decoratorCoffee;
};
class SogaCoffee:public DecoratorCoffee
{
public:
SogaCoffee(Coffee*m_pCoffee)
{
this->decoratorCoffee = m_pCoffee;
}
virtual void show()
{
decoratorCoffee->show();
addSoga();
}
void addSoga()
{
cout << "增加糖,价格增加1.5元" << endl << endl;
}
private:
Coffee*decoratorCoffee;
};
int _tmain(int argc, _TCHAR* argv[])
{
Coffee *commonCoffee = new CommonCoffee(1,"普通咖啡");
commonCoffee->show();
//抽象装饰类来装饰具体普通咖啡类,回调普通咖啡的函数
Coffee *decoratorCoffee = new DecoratorCoffee(commonCoffee);
decoratorCoffee->show();
cout << " 不同的装饰风格在子类自定义实现" << endl<<endl;
DecoratorCoffee *p = new MilkCoffee(decoratorCoffee);
p->show();
DecoratorCoffee *p1 = new SogaCoffee(decoratorCoffee);
p1->show();
return 0;
}