如何使用设计模式来构造系统--(7)
(聲明:本系列所用的模式都來自GOF23中,本系列并不是講23種經典設計模式,而是如何去使用這些模式)???
?
在前面的文章中,我們設計完成了員工工資,福利以及按照部門來區分員工,以及遍歷統計部門人員成本等業務邏輯,這些設計基本上可以滿足我們所設定的場景的變化,可是創建部門及人員樹的時候太復雜了,而且這種創建很容易發生變化,比如加入分公司,或者部門層級變動添加了層級的時候,創建的代碼一定就要修改.那么如何避免,封裝這個創建時的變化呢?
?
1.分析:來看看我們的意圖,我們要將復雜的部門創建過程封裝,使得同樣的構建過程可以創建不同的部門.那么我們就需要把創建單獨封裝,創建的過程也需要單獨封裝.
?
Gof23中的Builder(生成器)模式:將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。 與我們的意圖相符.那么我們就來使用Builder模式.
?
2.類圖:
?
?
3.代碼
?
首先封裝創建過程:
Codepublic?abstract?class?CompositeBuilder???//封裝創建過程
{
????public?abstract?PersonComposite?BuildComposite();
}
public?class?Builder:CompositeBuilder??//實現具體的創建過程
{
????public?override?PersonComposite?BuildComposite()??
????{
????????PersonComposite?root?=?new?PersonComposite();
????????StaffAndSalaryFactory?saf?=?new?StaffAndSalaryFactory();??//實例化工廠
????????for?(int?j?=?0;?j?<?5;j++?)
????????{
????????????PersonComposite?pc?=?new?PersonComposite();
????????????pc.Name?=?j.ToString();
????????????for?(int?i?=?0;?i?<?10;?i++)
????????????{
????????????????AbstractPerson?staff?=?saf.GetPerson();??//創建員工
????????????????staff.PersonName?=?"??涵舍愚人"+j.ToString()+i.ToString();
????????????????staff.PersonSalary?=?saf.GetSalary();//創建員工工資
????????????????if?(i?%?2?==?0)
????????????????{
????????????????????staff.PersonSalary.Salaryprize?=?BadPrize.badPrize;//使用單件初始化員工工資的績效部分
????????????????????//該員工工資為:6000+績效3000=9000
????????????????}
???????????????else
????????????????{
????????????????????staff.PersonSalary.Salaryprize?=?GoodPrize.goodPrize;//使用單件初始化員工工資的績效部分
????????????????????//該員工工資為:6000+績效6000=12000
????????????????}
????????????????pc.AddComposite(staff);//將Staff加到部門PC
????????????}
????????????root.Composite.Add(pc);
????????}
????????return?root;
????}
}
?
?
封裝創建:
Codepublic?class?Director??//封裝創建
{
????public?PersonComposite?GetPersonComposite(CompositeBuilder?cb)
????{
?????????return?cb.BuildComposite();
????}
}
?
客戶代碼:
?
Codeclass?Program
????{
????????static?void?Main(string[]?args)
????????{
????????????Builder?b?=?new?Builder();?//實例化具體Builder
????????????Director?d?=?new?Director();??//實例化Composite的創建
????????????PersonComposite?pc?=?d.GetPersonComposite(b);??//用d對象的固定方法創建PersonComposite
????????????Print(pc);?//調用輸出
????????????Console.Read();
????????}
????????public?static?void?Print(PersonComposite?pc)
????????{
????????????Listterator?list?=?new?Listterator(pc);??//實例化一個遍歷器,用來遍歷Composite的子節點
????????????while?(list.Next())??//遍歷下一個節點
????????????{
????????????????PersonComposite?spc?=?list.Current()?as?PersonComposite;//如果是部門,輸出部門名字
????????????????if?(!Equals(spc,?null))
????????????????{
????????????????????Console.Write("部門"+spc.Name+"\r\n");??
????????????????????Print(spc);?//如果是部門,則遞歸
????????????????}
????????????????else
????????????????{
????????????????????AbstractPerson?ap?=?list.Current()?as?AbstractPerson;??//如果是人員,輸出人員和工資
????????????????????if?(!Equals(ap,?null))
????????????????????{
????????????????????????Console.Write(ap.PersonName?+?"應得工資為"?+?ap.GetShouldpaid().ToString()+"\r\n");
????????????????????}
????????????????}
????????????}
????????}
????}
?
我們現在把創建過程封裝在了Build類里,當然這里可以是多個步驟,比如創建部門,創建組,創建人員等.
?
將創建完成Composite放到了Director類的固定方法中,我們可以先創建部門,然后組,再然后人員,甚至可以反過來,這樣創建過程不變,而Director的GetPersonComposite方法的創建步驟不同,就可以創建出不同的樹.這樣即使需求變化了,客戶代碼也不需要去改變,只要去創建不同的Builder和修改Director的方法就好了,如果Director用工廠方法來做,那么連它都不需要修改,而直接添加就好了,設計模式的原則之一就是添加優于修改.
?
輸出結果:
?
?
在創建時,給人員名字前加了個空格,就出現了一個簡單的樹,如果要寫樹,可以用我們前面用過的Stratege,來封裝樹控件前面的那小加號,減號,豎線等,然后在創建中使用這些封裝的策略.就OK了
?
這樣我們就完成了復雜的Composite的創建的封裝,但是這里面還有缺點:前面我們說了一個人可能身兼二職,尤其管理層的,更有這個可能,那么他就要出現在不同部門里,而我們現在的創建是一個節點一個對象,這樣我們就要浪費內存了...怎么解決?下一篇中我們將介紹!
?
??? 下一篇:如何使用設計模式來構造系統--(8)
?
轉載于:https://www.cnblogs.com/xugao918/archive/2008/08/20/1272228.html
總結
以上是生活随笔為你收集整理的如何使用设计模式来构造系统--(7)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: opencv的pnp()算法接口是相对于
- 下一篇: 基础知识:BT1120