設(shè)計(jì)模式之模板方法模式(TemplateMethod)

在地鐵上看《設(shè)計(jì)模式之禪》之模板方法模式。啊除破,還有這種模式,待閱讀完全章后琼腔,這不就是經(jīng)常使用的方法瑰枫。那什么是模板方法模式呢?

一、何為模板方法模式

定義一個(gè)操作中的算法的框架光坝,而將一些步驟延遲到子類中尸诽,使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。

模板方法在抽象類中定義好基本的流程盯另,各個(gè)子類根據(jù)其具體業(yè)務(wù)場景實(shí)現(xiàn)各個(gè)不同的操作性含。譬如說,我們在日常辦公中經(jīng)常用的審批流程鸳惯。審批的流程整體框架是固定的商蕴,申請人發(fā)起申請,審批人進(jìn)行簽字審批芝发。但是對于不同的審批(考勤審批绪商,離職審批,貸款審批等等)針對于審批人簽字前和簽字后的處理是不同的辅鲸。
離職審批:審批完成之后需要解除人員的相關(guān)系統(tǒng)權(quán)限格郁;請假審批,公司很人性瓢湃,只需要提個(gè)申請單理张,審批完無其他處理;貸款審批:審批之前需要判斷員工是否符合貸款資質(zhì)绵患。

二、模板方法通用類圖

模板方法類圖

三悟耘、基于模板方法模式設(shè)計(jì)的審批程類圖

ApprovalProcessBase 中Sign方法為模板方法落蝙,處理整體審批流程,SignBeforeSignAfter在考勤審批暂幼,離職審批筏勒,貸款審批有不同的處理。
介紹了這么多旺嬉,我們來看看具體的代碼示例管行。

四、代碼示例

先來看看抽象類ApprovalProcessBase的實(shí)現(xiàn)

  public abstract class ApprovalProcessBase
    {
        public virtual bool SignBefore(Approval model)
        {
            return true;
        }
        public virtual bool SignAfter(Approval model)
        {
            return true;
        }

        public bool Sign(Approval model)
        {
            var signBefore = this.SignBefore(model);
            var sign = SignHandle(model);
            //進(jìn)行簽字后操作
            return this.SignAfter(model);

        }
        /// <summary>
        /// 進(jìn)行簽字
        /// </summary>
        /// <param name=""></param>
        /// <returns></returns>
        private bool SignHandle(Approval model)
        {
          //校驗(yàn)簽字人密碼等等 
            return true;
        }
    }

各個(gè)實(shí)現(xiàn)類的實(shí)現(xiàn)邪媳。
公司管理很人性捐顷,請假只需要提交申請單,審批前和審批后無需任何處理雨效。默認(rèn)使用抽象類中ApprovalProcessBase定義的處理方式

    public class AttendanceProcess: ApprovalProcessBase
    {

    }

離職審批則不同了迅涮,審批后需要解除員工權(quán)限

    public class LeaveProcess: ApprovalProcessBase
    {
        public override bool SignAfter(Approval model)
        {
            //解除員工權(quán)限
          return  RemoveAuth();
        }
    }

假若公司規(guī)定,在公司工作超過3年徽龟,才可以向公司低息貸款叮姑,那么貸款申請審批,需要在審批前据悔,驗(yàn)證員工的貸款資質(zhì)

    public class LoanProcess: ApprovalProcessBase
    {
        public override bool SignBefotr(Approval model)
        {
            //驗(yàn)證員工貸款資質(zhì)
          return  ValidifEmployeeCertificate();
        }
    }

五传透、模板方法模式的擴(kuò)展

在通常情況下耘沼,簽字前簽字后處理的結(jié)果影響審批流程的處理。貸款審批朱盐,簽字前進(jìn)行資質(zhì)驗(yàn)證耕拷,若員工不滿足貸款條件,則不允許貸款托享,不能通過簽字骚烧,審批不通過。也就是抽象類ApprovalProcessBase中方法Sign依賴于SignBefore SignAfter的執(zhí)行結(jié)果闰围,那該如何設(shè)計(jì)呢赃绊?可以使用鉤子方法(Hook Method)。

鉤子方法:抽象類中定義的一個(gè)空實(shí)現(xiàn)的方法羡榴,子類可以實(shí)現(xiàn)它碧查,從而改變父類模板方法的執(zhí)行邏輯。在C#定義為虛方法校仑,關(guān)鍵詞virtual,Java中為abstract忠售。

看到這里,你也許會(huì)說那SignBeforeSIgnAfter不就是鉤子方法嗎迄沫?是的稻扬,他們就是鉤子方法,通過各自的條件改變羊瘩,影響模板方法的執(zhí)行泰佳。我們就可以將Sign方法做以下修改:

public bool Sign(Approval model)
        {
            var signBefore = this.SignBefore(model);
            if (!signBefore)
            {
                SendEmpolyeeNotice();//通知員工失敗原因
                return false;
            }
            var sign = SignHandle(model);
            //進(jìn)行簽字后操作
            var signAfter= this.SignAfter(model);
            if (signAfter)
            {
                SendEmployeeNoteceOfSuccess();//通知用戶成功
                return true;
            }
            CallBackTheOperation();//失敗將前面操作回滾
            return false;
        }

調(diào)用類

    public class HandleApprove
    {
        public bool Approve(string type)
        {
            switch (type)
            {
                case "Attendance":
                    return new AttendanceProcess().Sign();
                case "Leave":
                    return new LeaveProcess().Sign();
                case "Loan":
                    return new LoanProcess().Sign();
                default:
                    return false;
            }
        }
    }

六、模板方法模式優(yōu)點(diǎn)

通過這個(gè)例子我們可以看到模板方法有以下幾個(gè)優(yōu)點(diǎn):

  1. 封裝尘吗,可擴(kuò)展:將不變的地方封裝到父類實(shí)現(xiàn)逝她,將可變的部分通過繼承在子類繼續(xù)擴(kuò)展;
  2. 提取公共代碼睬捶,便于維護(hù)黔宛。

七、模板方法模式適用場景

  1. 代碼重構(gòu)時(shí):將相同的代碼抽取到父類擒贸,然后通過鉤子函數(shù)臀晃,約束其行為;
  2. 多個(gè)子類有公有的方法酗宋,且邏輯基本相同积仗;
  3. 重要,復(fù)雜的算法蜕猫,把核心算法設(shè)計(jì)為模板方法寂曹,其他相關(guān)細(xì)節(jié)功能由各個(gè)子類實(shí)現(xiàn)。

審批流程設(shè)計(jì)好了。現(xiàn)在有離職審批LeaveProcess隆圆,考勤審批AttendanceProcess漱挚,貸款審批LoanProcess,日后會(huì)增加其他的如報(bào)銷審批渺氧,轉(zhuǎn)正審批等等旨涝,那么每增加一個(gè)審批類別,就需要修改HandleApprove侣背,擴(kuò)展性不佳白华。希望審批種類增加,但是審批處理類HandleApprove不需修改贩耐,這該如何設(shè)計(jì)呢弧腥?

欲解決此問題,請看下一篇《設(shè)計(jì)模式之工廠方法模式》潮太。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末管搪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子铡买,更是在濱河造成了極大的恐慌更鲁,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奇钞,死亡現(xiàn)場離奇詭異澡为,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蛇券,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門缀壤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人纠亚,你說我怎么就攤上這事〗钕模” “怎么了蒂胞?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長条篷。 經(jīng)常有香客問我骗随,道長,這世上最難降的妖魔是什么赴叹? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任鸿染,我火速辦了婚禮,結(jié)果婚禮上乞巧,老公的妹妹穿的比我還像新娘涨椒。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布蚕冬。 她就那樣靜靜地躺著免猾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪囤热。 梳的紋絲不亂的頭發(fā)上猎提,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機(jī)與錄音旁蔼,去河邊找鬼锨苏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛棺聊,可吹牛的內(nèi)容都是我干的伞租。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼躺屁,長吁一口氣:“原來是場噩夢啊……” “哼肯夏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起犀暑,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤驯击,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后耐亏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體徊都,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年广辰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了暇矫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡择吊,死狀恐怖李根,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情几睛,我是刑警寧澤房轿,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站所森,受9級特大地震影響囱持,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜焕济,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一纷妆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧晴弃,春花似錦掩幢、人聲如沸逊拍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顺献。三九已至,卻和暖如春枯怖,著一層夾襖步出監(jiān)牢的瞬間注整,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工度硝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肿轨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓蕊程,卻偏偏與公主長得像椒袍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子藻茂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評論 2 349