本文為 C++ Software Design 書的第 35 節內容。
// Abstract class
class Item
{
public:
virtual ~Item() = default;
virtual Money price() const = 0;
};
// DecoratedItem class
class DecoratedItem : public Item
{
public:
explicit DecoratedItem(std::unique_ptr<Item> item) : item_(std::move(item)) {}
protected:
Item& item() {return *item_;}
Item const& item() const {return *item_;}
private:
std::unique_ptr<Item> item_;
};
// Product classes
class Book : public Item {};
class Ticket : public Item {};
// Decorators
class Discounted : public DecoratedItem
{
public:
Discounted(double discount, std::unique_ptr<Item> item) {}
};
class Taxed : public DecoratedItem
{
public:
Taxed(double taxRate, std::unique_ptr<Item> item) {}
};
// Usage
int main()
{
// 7% tax for books
std::unique_ptr<Item> book(
std::make_unique<Taxed>(0.07,
std::make_unique<Book>()));
// 10% tax and 20% discount for tickets
std::unique_ptr<Item> ticket(
std::make_unique<Taxed>(0.10,
std::make_unique<Discounted>(0.20,
std::make_unique<Ticket>())));
}
Decorator 與 Adaptor 模式的差別為其目的:Adaptor 模式的目的是轉化一個已有的介面,而 Decorator 目的是擴展及客製化已有的介面。Decorator 與 Strategy 模式較為接近,但前面已提過一個使用 Decorator 的例子。書中的比喻是 Strategy 模式比較像是改變一個類別的核心;而 Decorator 模式比較像是改變一個類別的外殼。
Decorator 模式最主要的問題為一層一層 virtual pointer 造成的效能問題。另外一個要小心的是 Decorator 的順序容易搞錯,像是先課稅再打折或先打折再課稅,都會造成其意義的不同。