從理發(fā)店流程抽象設計模式中的組合模式
今天下班客廳的燈確實亮堂了許多,照照鏡子感覺自己一下蒼老許多,看來還是燈光暗比較好,看不出來自己的憔悴啊,哈哈,其實還是頭發(fā)長了,決定出去剪發(fā)。
進到美發(fā)店,便有熱情的服務生招呼,顯示洗頭,挑選造型師,開始剪發(fā),剪發(fā)中被造型師推薦了各種各樣的收費項目,我只選擇了一樣軟化頭發(fā)。完畢之后,看了下單子哇塞、好貴噢,不過造型師給我剪的發(fā)型我還是很喜歡的,我決定以后還找他剪,但是又太貴,無奈中,發(fā)型師向我推薦了他們的會員卡,全場所有項目均5折,最近因為圣誕節(jié)還在搞活動這期間辦卡的可享受折上折8.6,我心想那這下就太劃算了,而且他們總店,分店都可以用,所以毫不猶豫的辦了張會員卡。。。囧。。。。
到家后稍微有點后悔,我竟然一時沖動花了那么多錢辦了張剪發(fā)的會員卡,不過辦也辦了,只好自己安慰安慰自己,心想,辦了卡可以打折上折,而且那么多分店想去哪家去哪家,頓時心情好為能好一點了,突然間想到了一個模式,跟現(xiàn)在的場景很合適,名字叫《組合模式》,為什么說跟組合模式很相似呢?
先看看組合模式的定義吧,在《大話設計模式一書中》組合模式的定義為:“將對象組合成樹形結(jié)構(gòu)以表示‘部分-整體’的層次結(jié)構(gòu)。組合模式使得用戶對單個對象和組合對象的使用具有一致性。”
那就拿我剪發(fā)辦卡的事情來分析一下吧。
首先,一張卡可以在總部,分店,加盟店使用,那么總部可以刷卡,分店也可以刷卡,加盟店也可以刷卡,這個屬性結(jié)構(gòu)的店面層級關(guān)系就明確啦。
那么,總店刷卡消費與分店刷卡消費是一樣的道理,那么總店與分店對會員卡的使用也具有一致性。
1.組合模式的例子
組合模式結(jié)構(gòu)圖:
那么組合模式的實例如下:
//抽象的部件類描述將來所有部件共有的行為
public abstract class Component
{
protected string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
//添加部件
public abstract void Add(Component component);
//刪除部件
public abstract void Remove(Component component);
//遍歷所有子部件
public abstract void eachChild();
}
//組合部件類
public class Leaf : Component
{
//葉子節(jié)點不具備添加的能力,所以不實現(xiàn)
public override void Add(Component component)
{
throw new NotImplementedException();
}
//葉子節(jié)點不具備添加的能力必然也不能刪除
public override void Remove(Component component)
{
throw new NotImplementedException();
}
//葉子節(jié)點沒有子節(jié)點所以顯示自己的執(zhí)行結(jié)果
public override void eachChild()
{
Console.WriteLine("{0}執(zhí)行了..",name);
}
}
//組合類
public class Composite : Component
{
//用來保存組合的部件
List<Component> myList = new List<Component>();
//添加節(jié)點 添加部件
public override void Add(Component component)
{
myList.Add(component);
}
//刪除節(jié)點 刪除部件
public override void Remove(Component component)
{
myList.Remove(component);
}
//遍歷子節(jié)點
public override void eachChild()
{
Console.WriteLine("{0}執(zhí)行了..", name);
foreach (Component c in myList)
{
c.eachChild();
}
}
}
static void Main(string[] args)
{
//構(gòu)造根節(jié)點
Composite rootComponent = new Composite();
rootComponent.Name = "根節(jié)點"
//添加兩個葉子幾點,也就是子部件
Leaf l = new Leaf();
l.Name = "葉子節(jié)點一"
Leaf l1 = new Leaf();
l1.Name = "葉子節(jié)點二"
rootComponent.Add(l);
rootComponent.Add(l1);
//遍歷組合部件
rootComponent.eachChild();
}
運行結(jié)果如下:
2.應用組合模式的會員卡消費
那么我們就根據(jù)我們會員卡的消費,來模擬一下組合模式的實現(xiàn)吧!let's go!
首先:
1.我們的部件有,總店,分店,加盟店!
2.我們的部件共有的行為是:刷會員卡
3.部件之間的層次關(guān)系,也就是店面的層次關(guān)系是,總店下有分店、分店下可以擁有加盟店。
有了我們這幾個必要條件后,我的要求就是目前店面搞活動當我在總店刷卡后,就可以累積相當于在所有下級店面刷卡的積分總額,設計的代碼如下:
/// <summary> /// 店面類 抽象出來的店面部件
/// </summary>
public abstract class Storefront
{
//店名
protected string storeName = string.Empty;
public string StoreName
{
get
{
return storeName;
}
}
//添加店面
public abstract void Add(Storefront store);
//刪除店面
public abstract void Remove(Storefront store);
//定義所有部件公用的行為 刷卡行為
public abstract void PayByCard();
}
public class StoreOrBranch : Storefront
{
//構(gòu)造函數(shù)
public StoreOrBranch() { }
public StoreOrBranch(string storeName)
{
this.storeName = storeName;
}
List<Storefront> myStoreList = new List<Storefront>();
//刷卡消費
public override void PayByCard()
{
Console.WriteLine("店面{0}的積分已累加進該會員卡", storeName);
foreach (Storefront sf in myStoreList)
{
sf.PayByCard();
}
}
//增加店面
public override void Add(Storefront store)
{
myStoreList.Add(store);
}
//解除店面
public override void Remove(Storefront store)
{
myStoreList.Remove(store);
}
}
public class JoinInStore : Storefront
{
//構(gòu)造函數(shù)
public JoinInStore() { }
public JoinInStore(string storeName)
{
this.storeName = storeName;
}
//刷卡消費
public override void PayByCard()
{
Console.WriteLine("店面{0}的積分已累加進該會員卡", storeName);
}
public override void Add(Storefront store)
{
throw new NotImplementedException();
}
public override void Remove(Storefront store)
{
throw new NotImplementedException();
}
}
static void Main(string[] args)
{
StoreOrBranch store = new StoreOrBranch("朝陽總店");
StoreOrBranch brach = new StoreOrBranch("東城分店");
JoinInStore jstore = new JoinInStore("海淀加盟店一");
JoinInStore jstore1 = new JoinInStore("上地加盟店二");
brach.Add(jstore);
brach.Add(jstore1);
store.Add(brach);
store.PayByCard();
}
運行結(jié)果如下:
這樣在累積所有子店面積分的時候,就不需要去關(guān)心子店面的個數(shù)了,也不用關(guān)系是否是葉子節(jié)點還是組合節(jié)點了,也就是說不管是總店刷卡,還是加盟店刷卡,都可以正確有效的計算出活動積分。
3.什么情況下使用組合模式
引用大話設計模式的片段:“當發(fā)現(xiàn)需求中是體現(xiàn)部分與整體層次結(jié)構(gòu)時,以及你希望用戶可以忽略組合對象與單個對象的不同,統(tǒng)一地使用組合結(jié)構(gòu)中的所有對象時,就應該考慮組合模式了。”
原文鏈接:http://www.cnblogs.com/doubleliang/archive/2011/12/27/2304104.html
【編輯推薦】