首先什麼是“策略模式”:動態地給一個對象添加一些額外的職責,就增加功能來說,裝飾模式比生成之類更為靈活。大話設計模式P48)
裝飾模式UML類圖:

1、其中Component類定義了一個對象接口,可以給這些對象動態添加職責
2、ConcreteComponent類定義了具體的對象,這些對象是被添加職責
3、Decorator類定義了裝飾類的接口,繼承於Component類,用於給對象添加職責
3、ConcreteDecorator類是裝飾類的具體對象,這些實現類可以額外添加自己的特性或者行為,來到給對象添加職責,靈活性比繼承要好。
代碼實現:
//Component
class Component {
public:
virtual void Operation() = 0;
};
//ConcreteComponent
class ConcreteComponent : public Component {
public:
void Operation() {
//具體對象的操作
}
};
//Decorator
class Decorator : public Component {
public:
void SetComponent(Component *pc) {
this->component = pc;
}
void Operation() {
if (component) {
component->Operation();
}
}
protected:
Component *component;
};
//ConcretrDecoratorA
class ConcretrDecoratorA : public Decorator {
public:
void Operation() {
Decorator::Operation();
addedState = "";
cout << addedState;
}
private:
string addedState; //增添特性
};
//ConcretrDecoratorB
class ConcretrDecoratorB : public Decorator {
public:
void Operation() {
Decorator::Operation();
AddedBehavior();
//do A
}
private:
void AddedBehavior() {
//do B
} //增添行為
};客戶端:
int main() {
ConcreteComponent *pc = new ConcreteComponent();
ConcretrDecoratorA *pda = new ConcretrDecoratorA();
ConcretrDecoratorB * pdb = new ConcretrDecoratorB();
pda->SetComponent(pc);
pdb->SetComponent(pda);
pdb->Operation();
return 0;
}下面以飲料添加輔料來實戰演練一下:
一杯普通的咖啡只要5元,添加奶泡1元),添加巧克力2元),添加方糖1.5元).....
所以以飲料類作為對象接口,有各種飲料的具體對象咖啡、奶茶、牛奶等等),和各種輔料類裝飾類),有奶泡,巧克力等等....
飲料類:
//飲料類
class Beverage {
public:
Beverage() {}
Beverage(string n, double c) : name(n), cost(c) {}
virtual void show() {
cout << name;
}
virtual double GetCost() {
return cost;
}
protected:
string name;
double cost;
};
//咖啡飲料,具體實現類
class Coffee : public Beverage {
public:
Coffee() : Beverage("咖啡", 5) {}
};
//奶茶飲料,具體實現類
class MilkTea : public Beverage {
public:
MilkTea() : Beverage("奶茶", 6) {}
};輔料類:
//裝飾類,輔料
class Decorator : public Beverage {
public:
void SetComponent(shared_ptr<Beverage> b) {
beverage = b;
}
void show() {
if (beverage) beverage->show();
}
double GetCost() {
if (beverage) return beverage->GetCost();
}
protected:
shared_ptr<Beverage> beverage;
};
//輔料類,奶泡
class MilkFoam : public Decorator {
public:
void show() {
Decorator::show();
cout << " + " << "奶泡";
}
double GetCost() {
return Decorator::GetCost() + 1;
}
};
//輔料類,巧克力
class Chocolate : public Decorator {
public:
void show() {
Decorator::show();
cout << " + " << "巧克力";
}
double GetCost() {
return Decorator::GetCost() + 2;
}
};
//輔料類,方糖
class Suger : public Decorator {
public:
void show() {
Decorator::show();
cout << " + " << "方糖";
}
double GetCost() {
return Decorator::GetCost() + 1.5;
}
};客戶端代碼:
int main() {
cout << "我要咖啡加方糖" << std::endl;
shared_ptr<Beverage> coffee(new Coffee());
shared_ptr<Decorator> suger(new Suger());
suger->SetComponent(coffee);
suger->show();
cout << "\n總價格: " << suger->GetCost() << std::endl;
cout << "我要奶茶,加奶泡和巧克力" << std::endl;
shared_ptr<Beverage> milktea(new MilkTea());
shared_ptr<Decorator> milkfoam(new MilkFoam());
shared_ptr<Decorator> chocolate(new Chocolate());
milkfoam->SetComponent(milktea);
chocolate->SetComponent(milkfoam);
chocolate->show();
cout << "\n總價格: " << chocolate->GetCost() << std::endl;
return 0;
}結果:

裝飾模式可以靈活地為對象增加職責,是開放-封閉原則的很好體現之一!
本文出自 “加和文的世界” 博客,請務必保留此出處http://xuyjun.blog.51cto.com/7470650/1304165