C++設(shè)計模式 week3 (Boolan)

“對象性能”模式

  • 面向?qū)ο蠛芎玫慕鉀Q了“抽象”的問題行您,但是不可避免地要付出一定的代價。對于通常情況來講剪廉,面向?qū)ο蟮某杀敬蠖伎梢院雎圆挥嬐扪5悄承┣闆r,面向?qū)ο笏鶐淼某杀颈仨氈?jǐn)慎處理斗蒋。
  • 典型模式
    • Singleton
    • Flyweight

Singleton 單件模式

動機(Motivation)

  • 在軟件系統(tǒng)中捌斧,經(jīng)常有這樣一些特殊的類笛质,必須保證它們在系統(tǒng)中只存在一個實例,才能確保它們的邏輯正確性捞蚂、以及良好的效率妇押。
  • 如何繞過常規(guī)的構(gòu)造器,提供一種機制來保證一個類只有一個實例姓迅?
  • 這應(yīng)該是類設(shè)計者的責(zé)任敲霍,而不是使用者的責(zé)任。

模式定義
保證一個類僅有一個實例丁存,并提供一個該實例的全局訪問點肩杈。
——《設(shè)計模式》GoF

要點總結(jié):

  • Singleton 模式中的實例構(gòu)造器可以設(shè)置為 protected 以允許子類派生。
  • Singleton 模式一般不要支持拷貝構(gòu)造函數(shù)和Clone接口解寝,因為這有可能導(dǎo)致多個對象實例扩然,與 Singleton 模式的初衷違背。
  • 如何實現(xiàn)多線程環(huán)境下安全的Singleton聋伦?注意對雙檢查鎖的正確實現(xiàn)夫偶。

Flyweight 享元模式

動機(Motivation):

  • 在軟件系統(tǒng)采用純粹對象方案的問題在于大量細(xì)粒度的對象會很快充斥在系統(tǒng)中,從而帶來很高的運行時代價——主要是指內(nèi)存需求方面的代價觉增。
  • 如何避免大量細(xì)粒度對象問題的同時兵拢,讓外部客戶程序仍然能夠透明地使用面向?qū)ο蟮姆绞絹磉M行操作?

模式定義:
運用共享技術(shù)有效地支持大量細(xì)粒度的對象抑片。
——《設(shè)計模式》GoF

要點總結(jié):

  • 面向?qū)ο蠛芎玫亟鉀Q了抽象性的問題卵佛,但是作為一個運行在機器中的程序?qū)嶓w,我們需要考慮對象的代價問題敞斋。Flyweight主要解決面向?qū)ο蟮拇鷥r問題截汪,一般不觸及面向?qū)ο蟮某橄笮詥栴}。
  • Flyweight 采用對象共享的作法來降低系統(tǒng)中對象的個數(shù)植捎,從而降低細(xì)粒度對象給系統(tǒng)帶來的內(nèi)存壓力衙解。在具體實現(xiàn)方面,要注意對象狀態(tài)的處理焰枢。
  • 對象的數(shù)量太大從而導(dǎo)致對象內(nèi)存開銷太大——什么樣的數(shù)量才算大蚓峦?這需要我們仔細(xì)的根據(jù)具體的應(yīng)用情況進行評估,而不能憑空臆斷济锄。

“狀態(tài)變化”模式

  • 在組件構(gòu)建過程中暑椰,某些對象的狀態(tài)經(jīng)常面臨變化,如何對這些變化進行有效的管理荐绝?同時又維持高層模塊的穩(wěn)定一汽?“狀態(tài)變化?模式為這一問題提供了一種解決方案低滩。

  • 典型模式

    • State
    • Memento

Memento 備忘錄

動機(Motivation):

  • 在軟件構(gòu)建過程中召夹,某些對象的狀態(tài)在轉(zhuǎn)換過程中岩喷,可能由于某種需要,要求程序能夠回溯到對象之前處于某個點時的狀態(tài)监憎。如果使用一些公有接口來讓其他對象得到對象的狀態(tài)纱意,便會暴露對象的細(xì)節(jié)實現(xiàn)。
    *如何實現(xiàn)對象狀態(tài)的良好保存于恢復(fù)鲸阔?但同時又不會因此而破壞對象本身的封裝性偷霉。

模式定義:
在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài)隶债,并在該對象之外保存這個狀態(tài)腾它。這樣以后就可以將該對象恢復(fù)到原先保存的狀態(tài)。
——《設(shè)計模式》GoF

要點總結(jié):

  • 備忘錄(Memento)存儲原發(fā)器(Originator)對象的內(nèi)部狀態(tài)死讹,在需要時恢復(fù)原發(fā)器狀態(tài)瞒滴。
  • Memento 模式的核心是信息隱藏,即Originator需要向外隱藏信息赞警,保持其封裝性妓忍。但同時又需要將狀態(tài)保持到外界(Memento)。
  • 由于現(xiàn)代語言運行時(如C#愧旦、Java等)都具有相當(dāng)?shù)膶ο笮蛄谢С质榔剩虼送捎眯瘦^高、又較容易正確實現(xiàn)的序列化方案來實現(xiàn)Memento模式笤虫。

State 狀態(tài)模式

動機(Motivation):

  • 在軟件構(gòu)建過程中旁瘫,某些對象的狀態(tài)如果發(fā)生改變,其行為也會隨之而發(fā)生變化琼蚯,比如文檔處于只讀狀態(tài)酬凳,其支持的行為和讀寫狀態(tài)支持的行為就可能完全不同。
  • 如何在運行時根據(jù)對象的狀態(tài)來透明地更改對象的行為遭庶?而不會為對象操作和狀態(tài)轉(zhuǎn)化之間引入緊耦合宁仔?

模式定義:
允許一個對象在其內(nèi)部狀態(tài)改變時改變它的行為。從而使對象看起來似乎修改了其行為峦睡。
——《設(shè)計模式》GoF

要點總結(jié):

  • State 模式將所有與一個特定狀態(tài)相關(guān)的行為都放入一個State的子類對象中翎苫,在對象狀態(tài)切換時,切換相應(yīng)的對象榨了;但同時維持State的接口煎谍,這樣實現(xiàn)了具體操作與狀態(tài)轉(zhuǎn)換之間的解耦。
  • 為不同的狀態(tài)引入不同的對象使得狀態(tài)轉(zhuǎn)換變得更加明確龙屉,而且可以保證不會出現(xiàn)狀態(tài)不一致的情況呐粘,因為轉(zhuǎn)換是原子性的——即要么徹底轉(zhuǎn)換過來,要么不轉(zhuǎn)換。
  • 如果State對象沒有實例變量事哭,那么各個上下文可以共享同一個State對象,從而節(jié)省對象開銷瓜富。

“數(shù)據(jù)結(jié)構(gòu)”模式

  • 常常有一些組件在內(nèi)部具有特定的數(shù)據(jù)結(jié)構(gòu)鳍咱,如果讓客戶程序依賴這些特定的數(shù)據(jù)結(jié)構(gòu),將極大的破壞組件的復(fù)用与柑。這時候谤辜,將這些特定數(shù)據(jù)結(jié)構(gòu)封裝在內(nèi)部,在外部提供統(tǒng)一的接口价捧,來實現(xiàn)與特定數(shù)據(jù)結(jié)構(gòu)無關(guān)的訪問丑念,是一種行之有效的解決方案。
  • 典型模式
    • Composite
    • Iterator
    • Chain of Responsibility

Composite模式

動機(Motivation):

  • 在軟件在某些情況下结蟋,客戶代碼過多地依賴于對象容器復(fù)雜的內(nèi)部實現(xiàn)結(jié)構(gòu)脯倚,對象容器內(nèi)部實現(xiàn)結(jié)構(gòu)(而非抽象接口)的變化將引起客戶代碼的頻繁變化,帶來代碼的維護性嵌屎、擴展性等弊端推正。
  • 如何將“客戶代碼與復(fù)雜的對象容器結(jié)構(gòu)”解耦?讓對象容器自己來實現(xiàn)自身的復(fù)雜結(jié)構(gòu)宝惰,從而使得客戶代碼就像處理簡單對象一樣來處理復(fù)雜的對象容器植榕。

模式定義
將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。Composite使得用戶對單個對象和組合對象的使用具有一致性(穩(wěn)定)尼夺。
——《設(shè)計模式》GoF

要點總結(jié):

  • Composite 模式采用樹形結(jié)構(gòu)來實現(xiàn)普遍存在的對象容器尊残,從而將“一對多”的關(guān)系轉(zhuǎn)化為“一對一”的關(guān)系,使得客戶代碼可以一致地(復(fù)用)處理對象和對象容器淤堵,無需關(guān)心處理的是單個的對象還是組合的對象容器寝衫。
  • 將“客戶代碼與復(fù)雜的對象容器結(jié)構(gòu)”解耦是Composite的核心思想,解耦之后粘勒,客戶代碼將與純粹的抽象接口——而非對象容器的內(nèi)部實現(xiàn)結(jié)構(gòu)——發(fā)生依賴竞端,從而更能“應(yīng)對變化”。
  • Composite模式在具體實現(xiàn)中庙睡,可以讓父對象中的子對象反向追溯事富;如果父對象有頻繁的遍歷需求,可使用緩存技巧來改善效率乘陪。

Iterator 迭代器

動機(Motivation):

  • 在軟件構(gòu)建過程中统台,集合對象內(nèi)部結(jié)構(gòu)常常變化各異。但對于這些集合對象啡邑,我們希望在不暴露其內(nèi)部結(jié)構(gòu)的同時贱勃,可以讓外部客戶代碼透明地訪問其中包含的元素;同時這種“透明遍歷”也為“同一種算法在多種集合對象上進行操作”提供了可能。
  • 使用面向?qū)ο蠹夹g(shù)將這種遍歷機制抽象為“迭代器對象”為“應(yīng)對變化中的集合對象”提供了一種優(yōu)雅的方式贵扰。

模式定義
提供一種方法順序訪問一個聚合對象中的各個元素仇穗,而又不暴露(穩(wěn)定)該對象的內(nèi)部表示。
——《設(shè)計模式》GoF

要點總結(jié):

  • 迭代抽象:訪問一個聚合對象的內(nèi)容而無需暴露它的內(nèi)部表示戚绕。
  • 迭代多態(tài):為遍歷不同的集合結(jié)構(gòu)提供一個統(tǒng)一的接口纹坐,從而支持同樣的算法在不同的集合結(jié)構(gòu)上進行操作。
  • 迭代器的健壯性考慮:遍歷的同時更改迭代器所在的集合結(jié)構(gòu)舞丛,會導(dǎo)致問題耘子。

Chain of Responsibility 職責(zé)鏈

動機(Motivation):

  • 在軟件構(gòu)建過程中,一個請求可能被多個對象處理球切,但是每個請求在運行時只能有一個接收者谷誓,如果顯示指定,將必不可少地帶來請求發(fā)送者與接受者的緊耦合吨凑。
  • 如何使請求的發(fā)送者不需要指定具體的接收者捍歪?讓請求的接收者自己在運行時決定來處理請求,從而使兩者解耦鸵钝。
    模式定義:
    使多個對象都有機會處理請求费封,從而避免請求的發(fā)送者和接收者之間的耦合關(guān)系。將這些對象連成一條鏈蒋伦,并沿著這條鏈傳遞請求弓摘,直到有一個對象處理它為止。
    ——《設(shè)計模式》GoF

要點總結(jié):

  • Chain of Responsibility 模式的應(yīng)用場合在于“一個請求可能有多個接收者痕届,但是最后真正的接收者只有一個”韧献,這時候請求發(fā)送者與接收者的耦合有可能出現(xiàn)“變化脆弱”的癥狀,職責(zé)鏈的目的就是將二者解耦研叫,從而更好地應(yīng)對變化锤窑。
  • 應(yīng)用了 Chain of Responsibility 模式后,對象的職責(zé)分派將更具靈活性嚷炉。我們可以在運行時動態(tài)添加/修改請求的處理職責(zé)渊啰。
  • 如果請求傳遞到職責(zé)鏈的末尾仍得不到處理,應(yīng)該有一個合理的缺省機制申屹。這也是每一個接受對象的責(zé)任绘证,而不是發(fā)出請求的對象的責(zé)任。

“行為變化”模式

  • 在組件的構(gòu)建過程中哗讥,組件行為的變化經(jīng)常導(dǎo)致組件本身劇烈的變化嚷那。“行為變化”模式將組件的行為和組件本身進行解耦杆煞,從而支持組件行為的變化魏宽,實現(xiàn)兩者之間的松耦合腐泻。
  • 典型模式
    • Command
    • Visitor

Command 命令模式

動機(Motivation):

  • 在軟件構(gòu)建過程中,“行為請求者”與“行為實現(xiàn)者”通常呈現(xiàn)一種“緊耦合”队询。但在某些場合——比如需要對行為進行“記錄派桩、撤銷/重做(undo/redo)、事務(wù)”等處理蚌斩,這種無法抵御變化的緊耦合是不適合的窄坦。
  • 在這種情況下,如何將“行為請求者”與“行為實現(xiàn)者”解耦凳寺?將一組行為抽象為對象,可以實現(xiàn)二者之間的松耦合彤侍。

模式定義:
將一個請求(行為)封裝為一個對象肠缨,從而使你可以用不同的請求對客戶進行參數(shù)化;對請求排隊或記錄請求日志盏阶,以及支持可撤銷的操作晒奕。
——《設(shè)計模式》GoF

要點總結(jié):

  • Command 模式的根本目的在于將“行為請求者”與“行為實現(xiàn)者”解耦,在面向?qū)ο笳Z言中名斟,常見的實現(xiàn)手段是“將行為抽象為對象”脑慧。
  • 實現(xiàn)Command接口的具體命令對象ConcreteCommand有時候根據(jù)需要可能會保存一些額外的狀態(tài)信息。通過使用Composite模式,可以將多個“命令”封裝為一個“復(fù)合命令”MacroCommand。
  • Command 模式與C++中的函數(shù)對象有些類似棺耍。但兩者定義行為接口的規(guī)范有所區(qū)別:Command以面向?qū)ο笾械摹敖涌?實現(xiàn)”來定義行為接口規(guī)范阻问,更嚴(yán)格,但有性能貌矿;C++函數(shù)對象以函數(shù)簽名來定義行為接口規(guī)范,更靈活,性能更高也物。

Visitor 訪問器

動機(Motivation):

  • 在軟件構(gòu)建過程中,由于需求的改變列疗,某些類層次結(jié)構(gòu)中常常需要增加新的行為(方法)滑蚯,如果直接在基類中做這樣的更改,將會給子類帶來很繁重的變更負(fù)擔(dān)抵栈,甚至破壞原有設(shè)計告材。
  • 如何在不更改類層次結(jié)構(gòu)的前提下,在運行時根據(jù)需要透明地為類層次結(jié)構(gòu)上的各個類動態(tài)添加新的操作古劲,從而避免上述問題创葡?

模式定義
表示一個作用于某對象結(jié)構(gòu)中的各元素的操作。使得可以在不改變(穩(wěn)定)各元素的類的前提下定義(擴展)作用于這些元素的新操作(變化)绢慢。
——《設(shè)計模式》GoF

要點總結(jié)

  • Visitor 模式通過所謂雙重分發(fā)(double dispatch)來實現(xiàn)在不更改(不添加新的操作-編譯時)Element類層次結(jié)構(gòu)的前提下灿渴,在運行時透明地為類層次結(jié)構(gòu)上的各個類動態(tài)添加新的操作(支持變化)洛波。
  • 所謂雙重分發(fā)即Visitor模式中間包括了兩個多態(tài)分發(fā)(注意其中的多態(tài)機制):第一個為accept方法的多態(tài)辨析;第二個為visitElementX方法的多態(tài)辨析骚露。
  • Visitor模式的做大缺點在于擴展類層次結(jié)構(gòu)(增添新的Element子類)蹬挤,會導(dǎo)致Visitor類的改變。因此Visitor模式適用于“Element類層次結(jié)構(gòu)穩(wěn)定棘幸,而其中的操作卻經(jīng)常面臨頻繁改動”焰扳。

“領(lǐng)域規(guī)則”模式

  • 在特定領(lǐng)域中,某些變化雖然頻繁误续,但可以抽象為某種規(guī)則吨悍。這時候,結(jié)合特定領(lǐng)域蹋嵌,將問題抽象為語法規(guī)則育瓜,從而給出在該領(lǐng)域下的一般性解決方案。
  • 典型模式
    • Interpreter

Interpreter 解析器

動機(Motivation)

  • 在軟件構(gòu)建過程中栽烂,如果某一特定領(lǐng)域的問題比較復(fù)雜躏仇,類似的結(jié)構(gòu)不斷重復(fù)出現(xiàn),如果使用普通的編程方法來實現(xiàn)將面臨非常頻繁的變化腺办。
  • 在這種情況下焰手,將特定領(lǐng)域的問題表達為某種語法規(guī)則下的句子,然后構(gòu)建一個解釋器來解釋這樣的句子怀喉,從而達到解決問題的目的书妻。

模式定義:
給定一個語言,定義它的文法的一種表示躬拢,并定義一種解釋器驻子,這個解釋器使用該表示來解釋語言中的句子。
——《設(shè)計模式》GoF

要點總結(jié):

  • Interpreter模式的應(yīng)用場合是Interpret模式應(yīng)用中的難點估灿,只有滿足“業(yè)務(wù)規(guī)則頻繁變化崇呵,且類似的結(jié)構(gòu)不斷重復(fù)出現(xiàn),并且容易抽象為語法規(guī)則的問題”才適合使用Interpreter模式馅袁。
  • 使用Interpreter模式來表示文法規(guī)則域慷,從而可以使用面向?qū)ο蠹记蓙矸奖愕亍皵U展”文法。
  • Interpreter模式比較適合簡單的文法表示汗销,對于復(fù)雜的文法表示犹褒,Interpreter模式會產(chǎn)生比較大的類層次結(jié)構(gòu),需要求助于語法分析生成器這樣的標(biāo)準(zhǔn)工具弛针。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末叠骑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子削茁,更是在濱河造成了極大的恐慌宙枷,老刑警劉巖掉房,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異慰丛,居然都是意外死亡卓囚,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門诅病,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哪亿,“玉大人,你說我怎么就攤上這事贤笆∮蓿” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵芥永,是天一觀的道長篡殷。 經(jīng)常有香客問我,道長恤左,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任搀绣,我火速辦了婚禮飞袋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘链患。我一直安慰自己巧鸭,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布麻捻。 她就那樣靜靜地躺著纲仍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贸毕。 梳的紋絲不亂的頭發(fā)上郑叠,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音明棍,去河邊找鬼乡革。 笑死,一個胖子當(dāng)著我的面吹牛摊腋,可吹牛的內(nèi)容都是我干的沸版。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼兴蒸,長吁一口氣:“原來是場噩夢啊……” “哼视粮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起橙凳,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蕾殴,失蹤者是張志新(化名)和其女友劉穎笑撞,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體区宇,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡娃殖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了议谷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炉爆。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖卧晓,靈堂內(nèi)的尸體忽然破棺而出芬首,到底是詐尸還是另有隱情,我是刑警寧澤逼裆,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布郁稍,位于F島的核電站,受9級特大地震影響胜宇,放射性物質(zhì)發(fā)生泄漏耀怜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一桐愉、第九天 我趴在偏房一處隱蔽的房頂上張望财破。 院中可真熱鬧,春花似錦从诲、人聲如沸左痢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽俊性。三九已至,卻和暖如春描扯,著一層夾襖步出監(jiān)牢的瞬間定页,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工绽诚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拯勉,地道東北人。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓憔购,卻偏偏與公主長得像宫峦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子玫鸟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354