小編這次要給大家分享的是詳解C#中TemplateMethod模式,文章內(nèi)容豐富,感興趣的小伙伴可以來了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。
大安市網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),大安市網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為大安市上千多家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)要多少錢,請找那個售后服務(wù)好的大安市做網(wǎng)站的公司定做!
一個真實(shí)的故事
大學(xué)的時候就開過一門課程,講設(shè)計(jì)模式,可是大學(xué)生沒什么編程實(shí)踐經(jīng)驗(yàn),在大學(xué)里面聽設(shè)計(jì)模式的感覺,就像聽天書。聽著都有道理,可是完全領(lǐng)會不到其中的奧妙,大抵原因就在于沒有走過彎路,沒有吃過設(shè)計(jì)不當(dāng)?shù)奶潯9湃嗽疲安偾髸月暎^千劍而后識器”,誠不欺我。
博主在之前的某個項(xiàng)目中,設(shè)計(jì)出了一些工具類,像屬性窗口,錯誤提示窗口,還有一個窗口管理類管理它們,當(dāng)時我實(shí)現(xiàn)工具保存時候的代碼是這樣的:
class WindowManager { private List<ITool> _Tools = new List<ITool>(); public void AddTool(ITool tool) { _Tools.Add(tool); } public void SaveAllTools() { foreach(var tool in _Tools) { tool.Save(); } } } interface ITool { bool BeforeSave(); void Save(); void AfterSave(); } class PropertyWindow : ITool { public bool BeforeSave() { //do something specific here return true; } public void Save() { if (BeforeSave()) { //do save AfterSave(); } } public void AfterSave() { } } class ErrorLis : ITool { public bool BeforeSave() { //do something specific here return true; } public void Save() { if (BeforeSave()) { //do save AfterSave(); } } public void AfterSave() { } }
當(dāng)時博主對這段代碼還挺滿意,完全沒有看出這兒有什么問題,覺得這簡直寫的太OO了,有類,有接口,有針對接口編程,至于新加的工具類,也不會影響原來的代碼,簡直太符合開閉原則了。老鐵,沒毛病!
好日子就這么繼續(xù)下去,每當(dāng)需要新添加一個工具,我就新加一個類,在類里面實(shí)現(xiàn)Save的邏輯,直到有一天,添加了一個ResourceControl
class ResourceControl : ITool { public bool BeforeSave() { //do something specific here return true; } public void Save() { if (!BeforeSave()) { //do save AfterSave(); } } public void AfterSave() { } }
在它的save里面,我把if(BeforeSave())寫成了if(!BeforeSave())。。。
于是,我又額外花了一些時間來找到這個問題,修改它并在下次添加新類的時候戰(zhàn)戰(zhàn)兢兢提醒自己不要犯這種低級的錯誤。那么,我們有沒有好的辦法來解決這個問題呢?
問題分析
其實(shí)就算每次添加新類的時候我們都能仔細(xì)的小心避免維護(hù)相同的邏輯,這段代碼的設(shè)計(jì)也還是有可以改進(jìn)的地方,比如,BeforeSave和AfterSave在這里作為接口ITool的一部分而公開,意味著客戶代碼可以自由的調(diào)用BeforeSave和AfterSave,然而這很可能并不是代碼作者的本意,畢竟,不調(diào)用Save而單獨(dú)調(diào)用BeforeSave和AfterSave有什么意義呢?讓客戶能夠看到更多不必要的方法,增加了客戶錯誤使用接口的可能性,不是么?
綜上所述,我們需要解決的問題如下:
這種場景下面,我們需要用到設(shè)計(jì)模式中的TemplateMethod(模版方法)模式。
TemplateMethod模式
在WIKI上面,TemplateMethod模式的定義如下,
In software engineering, the template method pattern is a behavioral design pattern that defines the program skeleton of an algorithm in an operation, deferring some steps to subclasses. It lets one redefine certain steps of an algorithm without changing the algorithm's structure.
大概意思就是,模版方法模式是一種行為類設(shè)計(jì)模式,允許軟件在更高的層次定義程序骨架,但是可以在子類推遲實(shí)現(xiàn)某些步驟。
類圖如下:
這完全符合我們的需求,讓我們試著修改我們的代碼。
使用TemplateMethod重新實(shí)現(xiàn)的代碼
class WindowManager { private List<AbstractTool> _Tools = new List<AbstractTool>(); public void AddTool(AbstractTool tool) { _Tools.Add(tool); } public void SaveAllTools() { foreach(var tool in _Tools) { tool.Save(); } } } abstract class AbstractTool { protected abstract bool BeforeSave(); protected abstract void DoSave(); protected abstract void AfterSave(); public void Save() { if(!BeforeSave()) { DoSave(); AfterSave(); } } } class PropertyWindow : AbstractTool { protected override bool BeforeSave() { //do something specific here return true; } protected override void DoSave() { } protected override void AfterSave() { } } class ErrorLis : AbstractTool { protected override bool BeforeSave() { //do something specific here return true; } protected override void DoSave() { } protected override void AfterSave() { } }
從上面我們可以看到,我們用一個抽象類AbstractTool代替之前的ITool接口,抽象類和接口的一個區(qū)別就是,抽象類可以在其中嵌入某些邏輯,所以我們在Save這個公共的非虛方法中,完全實(shí)現(xiàn)了我們的BeforeSave和AfterSave邏輯,僅僅留下了BeforeSave,AfterSave和DoSave給子類覆蓋。這樣我們得到的好處是:
結(jié)論
“紙上得來終覺淺,絕知此事要躬行”,祖宗的話,不會錯的,如果沒有一定的編程實(shí)踐和總結(jié),是沒有辦法領(lǐng)悟設(shè)計(jì)模式的,博主也是通過之前那個例子才領(lǐng)悟到TemplateMethod模式的妙用。
看完這篇關(guān)于詳解C#中TemplateMethod模式的文章,如果覺得文章內(nèi)容寫得不錯的話,可以把它分享出去給更多人看到。
本文標(biāo)題:詳解C#中TemplateMethod模式
鏈接分享:http://www.chinadenli.net/article48/pgiehp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、網(wǎng)站改版、企業(yè)網(wǎng)站制作、外貿(mào)建站、外貿(mào)網(wǎng)站建設(shè)、電子商務(wù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)