日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C++设计模式之模板模式(template)(行为型)

發(fā)布時(shí)間:2023/12/31 c/c++ 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++设计模式之模板模式(template)(行为型) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一 定義

模板方法模式是一種類(lèi)的行為型模式,在它的結(jié)構(gòu)圖中只有類(lèi)之間的繼承關(guān)系,沒(méi)有對(duì)象關(guān)聯(lián)關(guān)系,模板方法模式(Template Method Pattern)官方定義:定義一個(gè)操作中的算法的框架,而將一些步驟延遲到子類(lèi)中,使得子類(lèi)可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。

抽象模板中包含三種類(lèi)型的方法:?基本方法模板方法鉤子方法(Hook Method)。

基本方法——基本方法也叫做基本操作,是由子類(lèi)實(shí)現(xiàn)的方法,并且在模板方法被調(diào)用。

模板方法——核心方法,不允許子類(lèi)重寫(xiě),所以都會(huì)加上final修飾符,可以有一個(gè)或幾個(gè),一般是一個(gè)具體方法框架,按照固定的流程對(duì)基本方法的調(diào)度

鉤子方法——為了讓模板方法的執(zhí)行結(jié)果的更好地適應(yīng)因外界條件改變。比如說(shuō)銀行辦理業(yè)務(wù)為例,辦理業(yè)務(wù)是個(gè)模板方法,普通人要經(jīng)歷排隊(duì)、取號(hào)、等待、辦理四個(gè)基本流程,而Vip則不需要排隊(duì)、取號(hào)、等待,那么在設(shè)計(jì)的時(shí)候我們的抽象模板類(lèi)需要考慮到,于是乎你得需要在模板方法各基本方法調(diào)用之前增加條件判斷,那么用于設(shè)置這個(gè)條件的方法就是鉤子方法(Hook Method),鉤子方法也可以是抽象的還可以由子類(lèi)的一個(gè)方法返回值決定公共部分的執(zhí)行結(jié)果。

二 ULM圖

角色:

(1)AbstractClass:是抽象類(lèi),其實(shí)也就是一個(gè)抽象模板,定義并實(shí)現(xiàn)了一個(gè)模板方法。這個(gè)模板方法一般是一個(gè)具體方法,它給出了一個(gè)頂級(jí)邏輯的框架,而邏輯的組成步驟在相應(yīng)的抽象操作中,推遲到子類(lèi)實(shí)現(xiàn)。頂級(jí)邏輯也有可能調(diào)用一些具體方法。

(2)ConcreteClass:實(shí)現(xiàn)父類(lèi)所定義的一個(gè)或多個(gè)抽象方法。每一個(gè)AbstractClass都可以有任意多個(gè)ConcreteClass與之對(duì)應(yīng),而每一個(gè)ConcreteClass都可以給出這些抽象方法(也就是頂級(jí)邏輯的組成步驟)的不同實(shí)現(xiàn),從而使得頂級(jí)邏輯的實(shí)現(xiàn)各不相同。

總結(jié):當(dāng)不變的和可變的行為在方法的子類(lèi)實(shí)現(xiàn)中混合在一起的時(shí)候,不變的行為就會(huì)在子類(lèi)中重復(fù)出現(xiàn)。我們通過(guò)模板方法模式,把這些行為搬移到單一的地方,這樣幫助子類(lèi)擺脫重復(fù)的不變行為的糾纏。

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

良好的擴(kuò)展性,封裝不變部分,擴(kuò)展可變部分,把認(rèn)為是不變部分的算法封裝到父類(lèi)實(shí)現(xiàn),而可變部分的則可以通過(guò)繼承來(lái)繼續(xù)擴(kuò)展。例如增加一個(gè)新的功能很簡(jiǎn)單,只要再增加一個(gè)子類(lèi),實(shí)現(xiàn)父類(lèi)的基本方法就可以了。

提取公共部分代碼,便于維護(hù),減小維護(hù)升級(jí)成本,基本操作由父類(lèi)定義,子類(lèi)實(shí)現(xiàn)

基本方法是由子類(lèi)實(shí)現(xiàn)的,因此子類(lèi)可以通過(guò)擴(kuò)展的方式增加相應(yīng)的功能,符合開(kāi)閉原 則。

模板方法模式的缺點(diǎn)

通常抽象類(lèi)是負(fù)責(zé)聲明某一類(lèi)的事物的共同屬性和抽象方法,實(shí)現(xiàn)類(lèi)則是完成定義具體的特性和方法。但是模板方法模式卻顛倒了,抽象類(lèi)定義了部分抽象方法,由子類(lèi)實(shí)現(xiàn),子類(lèi)執(zhí)行的結(jié)果影響了父類(lèi)的結(jié)果,也就是子類(lèi)對(duì)父類(lèi)產(chǎn)生了影響。每個(gè)不同的實(shí)現(xiàn)都需要定義一個(gè)子類(lèi),這會(huì)導(dǎo)致類(lèi)的個(gè)數(shù)增加,系統(tǒng)更加龐大,設(shè)計(jì)也更加抽象,但是更加符合“單一職責(zé)原則”,使得類(lèi)的內(nèi)聚性得以提高。

適合使用模板方法模式的場(chǎng)景

  • 多個(gè)子類(lèi)有公有的方法,并且邏輯基本相同時(shí)。
  • 重要、復(fù)雜的算法,可以把核心算法設(shè)計(jì)為模板方法,周邊的相關(guān)細(xì)節(jié)功能則由各個(gè) 子類(lèi)實(shí)現(xiàn)。
  • 重構(gòu)時(shí),模板方法模式是一個(gè)經(jīng)常使用的模式,把相同的代碼抽取到父類(lèi)中,然后通過(guò)鉤子方法約束其行為。
  • ?四 實(shí)例

    1. 填寫(xiě)簡(jiǎn)歷表

    最近有個(gè)招聘會(huì),可以帶上簡(jiǎn)歷去應(yīng)聘了。但是,其中有一家公司不接受簡(jiǎn)歷,而是給應(yīng)聘者發(fā)了一張簡(jiǎn)歷表,上面有基本信息、教育背景、工作經(jīng)歷等欄,讓?xiě)?yīng)聘者按照要求填寫(xiě)完整。每個(gè)人拿到這份表格后,就開(kāi)始填寫(xiě)。如果用程序?qū)崿F(xiàn)這個(gè)過(guò)程,該如何做呢?一種方案就是用模板方法模式:定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類(lèi)中。模板方法使得子類(lèi)可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。我們的例子中,操作就是填寫(xiě)簡(jiǎn)歷這一過(guò)程,我們可以在父類(lèi)中定義操作的算法骨架,而具體的實(shí)現(xiàn)由子類(lèi)完成。下面給出它的UML圖。

    ?

    #include <iostream> #include <memory>//簡(jiǎn)歷 class Resume { protected: //保護(hù)成員virtual void SetPersonalInfo() {}virtual void SetEducation() {}virtual void SetWorkExp() {} public:void FillResume(){SetPersonalInfo();SetEducation();SetWorkExp();} };class ResumeA: public Resume { protected:void SetPersonalInfo(){std::cout << "A's PersonalInfo" << std::endl;}void SetEducation(){std::cout << "A's Education" << std::endl;}void SetWorkExp(){std::cout << "A's Work Experience" << std::endl;} };class ResumeB: public Resume { protected:void SetPersonalInfo(){std::cout << "B's PersonalInfo" << std::endl;}void SetEducation(){std::cout << "B's Education" << std::endl;}void SetWorkExp(){std::cout << "B's Work Experience" << std::endl;} };int main() {auto r1 = std::make_unique<ResumeA>();r1->FillResume();auto r2 = std::make_unique<ResumeB>();r2->FillResume();return 0; }

    ?

    五?模式的擴(kuò)展

    1)模板方法模式與控制反轉(zhuǎn)(好萊塢原則)

    在模板方法模式中,子類(lèi)不顯式調(diào)用父類(lèi)的方法,而是通過(guò)覆蓋父類(lèi)的方法來(lái)實(shí)現(xiàn)某些具體的業(yè)務(wù)邏輯,父類(lèi)控制對(duì)子類(lèi)的調(diào)用,這種機(jī)制被稱為好萊塢原則(Hollywood Principle),好萊塢原則的定義為:“不要給我們打電話,我們會(huì)給你打電話(Don‘t call us, we’ll call you)”。在好萊塢,把簡(jiǎn)歷遞交給演藝公司后就只有回家等待。由演藝公司對(duì)整個(gè)娛樂(lè)項(xiàng)的完全控制,演員只能被動(dòng)式的接受公司的差使,在需要的環(huán)節(jié)中,完成自己的演出。模板方法模式充分的體現(xiàn)了“好萊塢”原則。由父類(lèi)完全控制著子類(lèi)的邏輯,子類(lèi)不需要調(diào)用父類(lèi),而通過(guò)父類(lèi)來(lái)調(diào)用子類(lèi),子類(lèi)可以實(shí)現(xiàn)父類(lèi)的可變部份,卻繼承父類(lèi)的邏輯,不能改變業(yè)務(wù)邏輯。

    2)模板方法模式符合開(kāi)閉原則
    模板方法模式意圖是由抽象父類(lèi)控制頂級(jí)邏輯,并把基本操作的實(shí)現(xiàn)推遲到子類(lèi)去實(shí)現(xiàn),這是通過(guò)繼承的手段來(lái)達(dá)到對(duì)象的復(fù)用,同時(shí)也遵守了開(kāi)閉原則。

    父類(lèi)通過(guò)頂級(jí)邏輯,它通過(guò)定義并提供一個(gè)具體方法來(lái)實(shí)現(xiàn),我們也稱之為模板方法。通常這個(gè)模板方法才是外部對(duì)象最關(guān)心的方法。在上面的銀行業(yè)務(wù)處理例子中,templateMethodProcess這個(gè)方法才是外部對(duì)象最關(guān)心的方法。所以它必須是public的,才能被外部對(duì)象所調(diào)用。

    子類(lèi)需要繼承父類(lèi)去擴(kuò)展父類(lèi)的基本方法,但是它也可以覆寫(xiě)父類(lèi)的方法。如果子類(lèi)去覆寫(xiě)了父類(lèi)的模板方法,從而改變了父類(lèi)控制的頂級(jí)邏輯,這違反了“開(kāi)閉原則”。我們?cè)谑褂媚0宸椒J綍r(shí),應(yīng)該總是保證子類(lèi)有正確的邏輯。所以模板方法應(yīng)該定義為final的。所以AbstractClass類(lèi)的模板方法templateMethodProcess方法應(yīng)該定義為final。

    模板方法模式中,抽象類(lèi)的模板方法應(yīng)該聲明為final的。因?yàn)樽宇?lèi)不能覆寫(xiě)一個(gè)被定義為final的方法。從而保證了子類(lèi)的邏輯永遠(yuǎn)由父類(lèi)所控制。

    3)模板方法模式與對(duì)象的封裝性

    面向?qū)ο蟮娜筇匦?#xff1a;繼承,封裝,多態(tài)。

    對(duì)象有內(nèi)部狀態(tài)和外部的行為。封裝是為了信息隱藏,通過(guò)封裝來(lái)維護(hù)對(duì)象內(nèi)部數(shù)據(jù)的完整性。使得外部對(duì)象不能夠直接訪問(wèn)一個(gè)對(duì)象的內(nèi)部狀態(tài),而必須通過(guò)恰當(dāng)?shù)姆椒ú拍茉L問(wèn)。

    對(duì)象屬性和方法賦予指定的修改符(public、protected、private)來(lái)達(dá)到封裝的目的,使得數(shù)據(jù)不被外部對(duì)象惡意的訪問(wèn)及方法不被錯(cuò)誤調(diào)用導(dǎo)造成破壞對(duì)象的封裝性。

    降低方法的訪問(wèn)級(jí)別,也就是最大化的降低方法的可見(jiàn)度是一種很重要的封裝手段。最大化降低方法的可見(jiàn)度除了可以達(dá)到信息隱藏外,還能有效的降低類(lèi)之間的耦合度,降低一個(gè)類(lèi)的復(fù)雜度。還可以減少開(kāi)發(fā)人員發(fā)生的的錯(cuò)誤調(diào)用。

    一個(gè)類(lèi)應(yīng)該只公開(kāi)外部需要調(diào)用的方法。而所有為public方法服務(wù)的方法都應(yīng)該聲明為protected或private。如是一個(gè)方法不是需要對(duì)外公開(kāi)的,但是它需要被子類(lèi)進(jìn)行擴(kuò)展的或調(diào)用。那么把它定義為protected.否則應(yīng)該為private。

    顯而易見(jiàn),模板方法模式中的聲明為abstract的基本操作都是需要迫使子類(lèi)去實(shí)現(xiàn)的,它們僅僅是為模板方法服務(wù)的。它們不應(yīng)該被抽象類(lèi)(AbstractClass)所公開(kāi),所以它們應(yīng)該protected。

    因此模板方法模式中,迫使子類(lèi)實(shí)現(xiàn)的抽象方法應(yīng)該聲明為protected abstract。

    4)模板方法與勾子方法(hookMethod)

    模板方法模式的抽象類(lèi)定義方法:
    模板方法:一個(gè)模板方法是定義在抽象類(lèi)中的、把基本操作方法組合在一起形成一個(gè)總算法或一個(gè)總行為的方法。
    基本方法:基本方法是實(shí)現(xiàn)算法各個(gè)步驟的方法,是模板方法的組成部分。基本方法如下:
    ?抽象方法(Abstract Method)
    ?具體方法(Concrete Method)
    ?鉤子方法(Hook Method):“掛鉤”方法和空方法,
    hook方法在抽象類(lèi)中的實(shí)現(xiàn)為空,是留給子類(lèi)做一些可選的操作。如果某個(gè)子類(lèi)需要一些特殊額外的操作,則可以實(shí)現(xiàn)hook方法,當(dāng)然也可以完全不用理會(huì),因?yàn)閔ook在抽象類(lèi)中只是空方法而已。
    1)鉤子方法的引入使得子類(lèi)可以控制父類(lèi)的行為。
    2)最簡(jiǎn)單的鉤子方法就是空方法,也可以在鉤子方法中定義一個(gè)默認(rèn)的實(shí)現(xiàn),如果子類(lèi)不覆蓋鉤子方法,則執(zhí)行父類(lèi)的默認(rèn)實(shí)現(xiàn)代碼。
    3)比較復(fù)雜一點(diǎn)的鉤子方法可以對(duì)其他方法進(jìn)行約束,這種鉤子方法通常返回一個(gè)boolean類(lèi)型,即返回true或false,用來(lái)判斷是否執(zhí)行某一個(gè)基本方法。由子類(lèi)來(lái)決定是否調(diào)用hook方法。

    5) 小結(jié)

    1)模板方法模式是一種類(lèi)的行為型模式,在它的結(jié)構(gòu)圖中只有類(lèi)之間的繼承關(guān)系,沒(méi)有對(duì)象關(guān)聯(lián)關(guān)系。
    2)板方法模式是基于繼承的代碼復(fù)用基本技術(shù),模板方法模式的結(jié)構(gòu)和用法也是面向?qū)ο笤O(shè)計(jì)的核心之一。在模板方法模式中,可以將相同的代碼放在父類(lèi)中,而將不同的方法實(shí)現(xiàn)放在不同的子類(lèi)中。
    3)在模板方法模式中,我們需要準(zhǔn)備一個(gè)抽象類(lèi),將部分邏輯以具體方法以及具體構(gòu)造函數(shù)的形式實(shí)現(xiàn),然后聲明一些抽象方法來(lái)讓子類(lèi)實(shí)現(xiàn)剩余的邏輯。不同的子類(lèi)可以以不同的方式實(shí)現(xiàn)這些抽象方法,從而對(duì)剩余的邏輯有不同的實(shí)現(xiàn),這就是模板方法模式的用意。模板方法模式體現(xiàn)了面向?qū)ο蟮闹T多重要思想,是一種使用頻率較高的模式。

    ?

    總結(jié)

    以上是生活随笔為你收集整理的C++设计模式之模板模式(template)(行为型)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。