許多Design Pattern介紹概念時,通常都會使用Class diagram來介紹
這邊舉Decorator Pattern來當作例子,搭配UML與實際的Sample code
大家就會知道為什麼UML是抽象、穩定、容易溝通的
Decorator Pattern目的:
Add new functionality dynamically to existing objects, or remove it
針對基底object動態地新增function或移除function,也可賦予新的operation或state
特性
* The original object is unaware of any decorations.
* There is no one big feature-laden class with all the options in it.
* The decorations are independent of each other.
* The decorations can be composed together in a mix-and-match fashion.
簡單的說,新的object與原本的object都一樣,
透過interface的implement可以比用inheritance+overrides來的更有彈性。
(如果你只會有一個新的object,那就可以直接用inheritance,通常為了保留彈性,還是會用implement)
書上的例子相單簡單易懂,
is A的部分,為Implement。
has A的部分,則是將Interface丟進去新的object(即新的Decorator) 建構式。
程式碼的部分也相當好理解,
using System;
class DecoratorPattern {
// Decorator Pattern Judith Bishop Dec 2006
// Shows two decorators and the output of various
// combinations of the decorators on the basic component
interface IComponent {
string Operation();
}
class Component : IComponent {
public string Operation () {
return "I am walking ";
}
}
class DecoratorA : IComponent {
IComponent component;
public DecoratorA (IComponent c) {
component = c;
}
public string Operation() {
string s = component.Operation();
s += "and listening to Classic FM ";
return s;
}
}
class DecoratorB : IComponent {
IComponent component;
public string addedState = "past the Coffee Shop ";
public DecoratorB (IComponent c) {
component = c;
}
public string Operation () {
string s = component.Operation ();
s += "to school ";
return s;
}
public string AddedBehavior() {
return "and I bought a cappuccino ";
}
}
class Client {
static void Display(string s, IComponent c) {
Console.WriteLine(s+ c.Operation());
}
static void Main() {
Console.WriteLine("Decorator Pattern\n");
IComponent component = new Component();
Display("1. Basic component: ", component);
Display("2. A-decorated : ", new DecoratorA(component));
Display("3. B-decorated : ", new DecoratorB(component));
Display("4. B-A-decorated : ", new DecoratorB(
new DecoratorA(component)));
// Explicit DecoratorB
DecoratorB b = new DecoratorB(new Component());
Display("5. A-B-decorated : ", new DecoratorA(b));
// Invoking its added state and added behavior
Console.WriteLine("\t\t\t"+b.addedState + b.AddedBehavior());
}
}
}
結果
**/* Output
Decorator Pattern
建議大家可以先從結果開始看,接著看Main(),再推回去看每一個class,搭配UML服用。
重點解釋:
* 每一個instance都是IComponent
* Component為每個instance的基底,且自己也是一個完整的instance
* Decorator的instance建構式,將IComponent丟進來當作參數,即可使用丟進來的IComponent的operation。
* Decorator除了可以使用丟進來的IComponent的operation,還可以定義自己實作IComponent的operation或attribute。
* 可以延伸出無限多種Decorator來implement自己期望的IComponent。
最後在強調一下,Decorator Pattern最主要的目的,
是用來解決如何針對一個基底的object,
動態地去新增、移除新的或已經存在的function,不用繼承,也可以修改新object的attribute或operation。