上周講述了DOF設(shè)計(jì)模式中的“對(duì)象創(chuàng)建”模式和“接口隔離”模式,本周講述DOF設(shè)計(jì)模式中的剩下的模式,“對(duì)象性能”模式(包括Singleton單件模式和Flyweight享元模式)、“狀態(tài)變化”模式(包括State狀態(tài)模式和Memento備忘錄)、“數(shù)據(jù)結(jié)構(gòu)”模式(包括Composite組合模式、Iterator迭代器和Chain of Responsibility職責(zé)鏈)、“行為變化”模式(包括Command命令模式和Visitor訪問(wèn)器)以及“領(lǐng)域規(guī)則”模式(包括Interpreter解析器)。
(一)“對(duì)象性能”模式
面向?qū)ο蠛芎玫慕鉀Q了“抽象”的問(wèn)題,但是必不可免地要付出一定的代價(jià)。對(duì)于通常情況來(lái)講,面向?qū)ο蟮某杀敬蠖伎梢院雎圆挥?jì)。但是某些情況,面向?qū)ο笏鶐?lái)的成本必須謹(jǐn)慎處理。
典型模式:Singleton、Flyweight。
1、Singleton單件模式
Singleton單件模式定義:保證一個(gè)類(lèi)僅有一個(gè)實(shí)例,并提供一個(gè)該實(shí)例的全局訪問(wèn)點(diǎn)。
Singleton單件模式動(dòng)機(jī):在軟件系統(tǒng)中,經(jīng)常有這樣一個(gè)特殊的類(lèi),必須保證它們?cè)谙到y(tǒng)中只存在一個(gè)示例,才能確保他們的邏輯正確性、以及良好的效率。
如何繞過(guò)常規(guī)的構(gòu)造器,提供一種機(jī)制來(lái)保證一個(gè)類(lèi)只有一個(gè)實(shí)例?這個(gè)應(yīng)該類(lèi)設(shè)計(jì)者的責(zé)任,而不是使用者的責(zé)任。
優(yōu)點(diǎn):減少了時(shí)間和空間的開(kāi)銷(xiāo)(new實(shí)例的開(kāi)銷(xiāo));提高了封裝性,使得外部不易改動(dòng)實(shí)例。
缺點(diǎn):懶漢式是以時(shí)間換空間的方式;餓漢式是以空間換時(shí)間的方式。
Singleton單件模式的結(jié)構(gòu)如圖1所示。
總結(jié):
(1)Singleton模式中的實(shí)例構(gòu)造器可以設(shè)置為protected以允許子類(lèi)派生。
(2)Singleton模式一般不要支持拷貝構(gòu)造函數(shù)和Clone接口,因?yàn)檫@有可能會(huì)導(dǎo)致多個(gè)對(duì)象實(shí)例,與Singleton模式的初衷相違背。
(3)實(shí)現(xiàn)多線(xiàn)程環(huán)境下安全的Singleton,注意對(duì)雙檢查鎖的正確實(shí)現(xiàn)。
雙檢查鎖,在lock的前后判斷m_instance是否為空。因?yàn)榭赡芏鄠€(gè)線(xiàn)程都走進(jìn)到m_instance==nullptr分支,所以之后每個(gè)線(xiàn)程在獲得鎖之后要再次判斷m_instance==nullptr,來(lái)確保m_instance不會(huì)被重復(fù)實(shí)例化。但可能出現(xiàn)內(nèi)存讀寫(xiě)reorder問(wèn)題,在經(jīng)過(guò)編譯器優(yōu)化后,實(shí)例化Singleton可能不是按照分配空間、構(gòu)造和地址賦值給指針的順序進(jìn)行的,而是按照分配空間、指針賦值、構(gòu)造這三個(gè)步驟,當(dāng)一個(gè)線(xiàn)程執(zhí)行到指針賦值后,如果有另一個(gè)線(xiàn)程進(jìn)來(lái)判斷m_instance指針不為空,直接返回m_instance,并直接使用這個(gè)指針,那就會(huì)發(fā)生錯(cuò)誤,因?yàn)榈谝粋€(gè)線(xiàn)程還沒(méi)有執(zhí)行構(gòu)造器,所以這時(shí)雙檢查鎖也就是失效了。解決辦法,將變量聲明為volatile防止編譯器優(yōu)化代碼。
2、Flyweight享元模式
Flyweight享元模式定義:運(yùn)用共享技術(shù)有效地支持大量的細(xì)粒度對(duì)象。
Flyweight享元模式動(dòng)機(jī):在軟件系統(tǒng)中采用純粹對(duì)象方案的問(wèn)題 在于大量細(xì)粒度的對(duì)象會(huì)很快充斥在系統(tǒng)中,從而帶來(lái)很高的運(yùn)行時(shí)代價(jià)——主要指內(nèi)存需求方面的代價(jià)。
Flyweight享元模式的結(jié)構(gòu)如圖2所示。
總結(jié):
(1)面向?qū)ο蠛芎玫慕鉀Q了抽相性的問(wèn)題,但是作為一個(gè)運(yùn)行在機(jī)器中的程序?qū)嶓w,我們需要考慮對(duì)象的代價(jià)問(wèn)題。Flyweight主要解決面向的代價(jià)問(wèn)題,一般不觸及面向?qū)ο蟮某橄笮詥?wèn)題。
(2)Flyweight采用對(duì)象共享的做法來(lái)降低系統(tǒng)中的對(duì)象的個(gè)數(shù),從而降低細(xì)粒度對(duì)象給系統(tǒng)帶來(lái)的內(nèi)存壓力。在具體實(shí)現(xiàn)方面,要注意對(duì)像狀態(tài)的處理。
(3)對(duì)象的數(shù)量太大,從而導(dǎo)致對(duì)像內(nèi)存開(kāi)銷(xiāo)加大——什么樣的數(shù)量才算大?這需要我們仔細(xì)根據(jù)具體應(yīng)用情況進(jìn)行評(píng)估,而不能憑空臆斷。
(二)“狀態(tài)變化”模式
在組建構(gòu)建過(guò)程中,某些對(duì)象的狀態(tài)經(jīng)常面臨變化,“狀態(tài)變化”模式可以使變化進(jìn)行有效的管理,同時(shí)又維持高層模塊的穩(wěn)定。
典型模式:State、Memento。
3、State狀態(tài)模式
State狀態(tài)模式定義:允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變是改變它的行為。從而使對(duì)像看起來(lái)似乎修改其行為。
State狀態(tài)模式動(dòng)機(jī):在軟件構(gòu)建過(guò)程中,某些對(duì)象的狀態(tài)如果改變,其行為也會(huì)隨之而發(fā)生變化,比如文檔處于只讀狀態(tài),其支持的行為和讀寫(xiě)狀態(tài)支持的行為就可能會(huì)完全不同。
如何在運(yùn)行時(shí)根據(jù)對(duì)象的狀態(tài)來(lái)透明地更改對(duì)象的行為?而不會(huì)為對(duì)象操作和狀態(tài)轉(zhuǎn)化之間引入緊耦合?
優(yōu)點(diǎn):
(1)狀態(tài)模式將與特定狀態(tài)相關(guān)的行為局部化,并且將不同狀態(tài)的行為分割開(kāi)來(lái)。
(2)所有狀態(tài)相關(guān)的代碼都存在于某個(gè)ConcereteState中,所以通過(guò)定義新的子類(lèi)很容易地增加新的狀態(tài)和轉(zhuǎn)換。
(3)狀態(tài)模式通過(guò)把各種狀態(tài)轉(zhuǎn)移邏輯分不到State的子類(lèi)之間,來(lái)減少相互間的依賴(lài)。
?缺點(diǎn):導(dǎo)致較多的ConcreteState子類(lèi)。
State狀態(tài)模式的結(jié)構(gòu)如圖3所示。
總結(jié):
(1)通過(guò)擴(kuò)展子類(lèi),來(lái)添加進(jìn)狀態(tài),解決狀態(tài)轉(zhuǎn)化問(wèn)題,當(dāng)有if...else時(shí),可以轉(zhuǎn)換成此方法。
(2)State模式將所有與一個(gè)特定狀態(tài)相關(guān)的行為都放入一個(gè)State的子類(lèi)對(duì)象中,在對(duì)像狀態(tài)切換時(shí), 切換相應(yīng)的對(duì)象;但同時(shí)維持State的接口,這樣實(shí)現(xiàn)了具體操作與狀態(tài)轉(zhuǎn)換之間的解耦。
(3)為不同的狀態(tài)引入不同的對(duì)象使得狀態(tài)轉(zhuǎn)換變得更加明確,而且可以保證不會(huì)出現(xiàn)狀態(tài)不一致的情況,因?yàn)檗D(zhuǎn)換是原子性的——即要么徹底轉(zhuǎn)換過(guò)來(lái),要么不轉(zhuǎn)換。
(4)如果State對(duì)象沒(méi)有實(shí)例變量,那么各個(gè)上下文可以共享同一個(gè)State對(duì)象,從而節(jié)省對(duì)象開(kāi)銷(xiāo)。
4、Memento備忘錄
Memento備忘錄模式定義:在不破壞封裝性的前提下,不活一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)像之外保存這個(gè)狀態(tài)。這樣以后就可以將該對(duì)像恢復(fù)到原想保存的狀態(tài)。
Memento備忘錄模式動(dòng)機(jī):在軟件構(gòu)建過(guò)程中,某些對(duì)象的狀態(tài)在轉(zhuǎn)會(huì)過(guò)程中,可能由于某種需求,要求程序能夠回溯到對(duì)像之前處于某個(gè)點(diǎn)時(shí)的狀態(tài)。如果使用一些公有借口來(lái)讓其它對(duì)象得到對(duì)象的狀態(tài),便會(huì)暴露對(duì)象的實(shí)現(xiàn)細(xì)節(jié)。
如何實(shí)現(xiàn)對(duì)象狀態(tài)的良好保存與恢復(fù)?但同時(shí)又不會(huì)因此而破壞對(duì)象本身的封裝性。
Memento備忘錄模式的結(jié)構(gòu)如圖4所示。
總結(jié):
(1)在狀態(tài)轉(zhuǎn)化時(shí),還原到某一個(gè)狀態(tài),用原發(fā)器創(chuàng)建備忘錄,保存。
(2)備忘錄(Memento)存儲(chǔ)原發(fā)器(Originator)對(duì)象的內(nèi)部狀態(tài),在需要時(shí)恢復(fù)原發(fā)器的狀態(tài)。
(3)Memento模式的核心是信息隱藏,即Originator需要向外接隱藏信息,保持其封裝性。但同時(shí)又需要將其狀態(tài)保持到外界(Memento)
(4)由于現(xiàn)代語(yǔ)言運(yùn)行時(shí)(如C#、java等)都具有相當(dāng)?shù)膶?duì)象序列化支持,因此往往采用效率較高、又較容易正確實(shí)現(xiàn)的序列化方案來(lái)實(shí)現(xiàn)Memento模式。
(三)“數(shù)據(jù)結(jié)構(gòu)”模式
常常有一些組建在內(nèi)部具有特定的數(shù)據(jù)結(jié)構(gòu),如果讓客戶(hù)程序依賴(lài)這些特定的數(shù)據(jù)結(jié)構(gòu),將極大的破壞組件的復(fù)用。這時(shí)候,將這些數(shù)據(jù)結(jié)構(gòu)封裝在內(nèi)部,在外部提供統(tǒng)一的接口,來(lái)實(shí)現(xiàn)與特定數(shù)據(jù)結(jié)構(gòu)無(wú)關(guān)的訪問(wèn),是一種行之有效的解決方案。
典型模式:Composite、Iterator、Chain of Responsibility。
5、Composite組合模式
Composite組合模式定義:將對(duì)象組合成樹(shù)形結(jié)構(gòu)以表示“部分-整體”的層級(jí)結(jié)構(gòu)。Compisite使得用戶(hù)對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性(穩(wěn)定)。
Composite組合模式動(dòng)機(jī):軟件在某些情況下,客戶(hù)代碼過(guò)多地依賴(lài)于對(duì)像容器復(fù)雜的內(nèi)部實(shí)現(xiàn)結(jié)構(gòu),對(duì)象容器內(nèi)部實(shí)現(xiàn)結(jié)構(gòu)(而非抽象接口)的變化將因其客戶(hù)代碼的頻繁變化,帶來(lái)了代碼的維護(hù)性、擴(kuò)展性等弊端。
如何將“客戶(hù)代碼與復(fù)雜的對(duì)象容器結(jié)構(gòu)”解耦?讓對(duì)象容器自己來(lái)實(shí)現(xiàn)自身的復(fù)雜結(jié)構(gòu),從而使得客戶(hù)代碼就像處理簡(jiǎn)單對(duì)象一樣來(lái)處理復(fù)雜的對(duì)象容器?
Composite組合模式的結(jié)構(gòu)如圖5所示。
總結(jié):
(1)Composite模式采用樹(shù)形結(jié)構(gòu)來(lái)實(shí)現(xiàn)普遍存在的對(duì)象容器,從而將“一對(duì)多”的關(guān)系轉(zhuǎn)化為“一對(duì)一”的關(guān)系,使得客戶(hù)代碼可以一致地(復(fù)用)處理對(duì)象和對(duì)象容器,無(wú)需關(guān)心處理的是單個(gè)對(duì)象還是組合的對(duì)象容器。
(2)將“客戶(hù)代碼與復(fù)雜的對(duì)象容器結(jié)構(gòu)”解耦是Composite的核心思想,解耦之后,客戶(hù)代碼將與純粹的抽象接口——而非對(duì)像容器的內(nèi)部實(shí)現(xiàn)結(jié)構(gòu)——發(fā)生依賴(lài),從而更能“應(yīng)對(duì)變化”。
(3)Composite模式在具體實(shí)現(xiàn)中,可以讓父對(duì)象中的子對(duì)象反向追溯;如果父對(duì)象有頻繁的遍歷需求,可使用緩存技巧來(lái)改善效率。
6、Iterator迭代器
Iterator迭代器模式定義:提供一種方法順序訪問(wèn)一個(gè)聚合對(duì)象中的各個(gè)元素,而又不暴露(隔離變化,穩(wěn)定)該對(duì)象的內(nèi)部表示。
Iterator迭代器模式動(dòng)機(jī):在軟件構(gòu)建過(guò)程中,集合對(duì)象內(nèi)部結(jié)構(gòu)常常變化各異。但對(duì)于這些集合對(duì)象,我們希望在不暴露其內(nèi)部結(jié)構(gòu)的同時(shí),可以讓外部客戶(hù)代碼透明的訪問(wèn)其中包含的元素;同時(shí)這種“透明遍歷”也為“同一種算法在多種集合對(duì)象上進(jìn)行操作”提供了可能。
使用面向?qū)ο蠹夹g(shù)將這種遍歷機(jī)制抽象為“迭代器對(duì)象”為“因?qū)ψ兓械募蠈?duì)象”提供了一種優(yōu)雅的方式。
Iterator迭代器模式的結(jié)構(gòu)如圖6所示。
總結(jié):
(1)迭代抽象:訪問(wèn)一個(gè)聚合對(duì)象的內(nèi)容而無(wú)需暴露他的內(nèi)部表示。
(2)迭代多態(tài):為遍歷不同的集合結(jié)構(gòu)提供一個(gè)統(tǒng)一的接口,從而支持同樣的算法在不同的集合結(jié)構(gòu)上進(jìn)行操作。
(3)迭代器健壯性考慮:遍歷的同時(shí)更改迭代器所在的集合結(jié)構(gòu),會(huì)導(dǎo)致問(wèn)題。
7、Chain of Responsibility職責(zé)鏈
Chain of Responsibility職責(zé)鏈模式定義:使多個(gè)對(duì)像都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系。將這些對(duì)像連成一條鏈,并沿著這條鏈傳遞請(qǐng)求,直到有一個(gè)對(duì)象處理它為止。
Chain of Responsibility職責(zé)鏈模式動(dòng)機(jī):在軟件構(gòu)建的過(guò)程中,一個(gè)請(qǐng)求可能被多個(gè)對(duì)象處理,但是每個(gè)請(qǐng)求在運(yùn)行時(shí)只能有一個(gè)接受者,如果顯示指定,將必不可少的帶來(lái)請(qǐng)求發(fā)送者與接受者的耦合。
如何使請(qǐng)求的發(fā)送者不需要指定具體的接受者?讓請(qǐng)求的接受者自己在運(yùn)行時(shí)決定來(lái)處理請(qǐng)求,從而使兩者解耦。
Chain of Responsibility職責(zé)鏈模式的結(jié)構(gòu)如圖7所示。
總結(jié):
(1)Chain of Responsibility模式的應(yīng)用場(chǎng)合在于“一個(gè)請(qǐng)求可能有多個(gè)接受者,但是最后真正接受者只有一個(gè)”,這時(shí)候請(qǐng)求發(fā)送者與接受者的耦合可能出現(xiàn)“變化脆弱”的癥狀,職責(zé)鏈的目的就是將二者解耦,從而更好的應(yīng)對(duì)變化。
(2)應(yīng)用了Chain of Responsibility模式后,對(duì)象的職責(zé)分派將更具靈活性。我們可以在運(yùn)行時(shí)動(dòng)態(tài)添加/修改請(qǐng)求的處理指責(zé)。
(3)如果請(qǐng)求傳遞到職責(zé)鏈的末尾仍得不到處理,應(yīng)該有一個(gè)合理的缺省機(jī)制。這也是每一個(gè)接受者對(duì)象的責(zé)任,而不是發(fā)出請(qǐng)求的對(duì)象的責(zé)任。
(四)“行為變化”模式
在組建的構(gòu)建過(guò)程中,組建行為的變化經(jīng)常導(dǎo)致組建本身劇烈的變化?!靶袨樽兓蹦J綄⒔M建的行為和組建本身進(jìn)行解耦,從而主持組件的變化,實(shí)現(xiàn)兩者之間的松耦合。
典型模式:Command、Visitor。
8、Command命令模式
Command命令模式模式定義:將一個(gè)請(qǐng)求(行為)封裝為對(duì)象,從而使你可用不同的請(qǐng)求,對(duì)客戶(hù)進(jìn)行參數(shù)化;對(duì)請(qǐng)求排隊(duì)或記錄請(qǐng)求日志以及支持可撤銷(xiāo)的操作。
Command命令模式動(dòng)機(jī):在軟件構(gòu)建構(gòu)成中,“行為請(qǐng)求者”與“行為實(shí)現(xiàn)者”通常呈現(xiàn)一種“緊耦合”。但在某些場(chǎng)合——比如需要對(duì)行為進(jìn)行“記錄、撤銷(xiāo)(undo)、事務(wù)”等處理,這種無(wú)法抵御變化的緊耦合是不合適的。
在這種情況下,如何將“行為請(qǐng)求者”與“行為實(shí)現(xiàn)者”解耦?將一組行為抽象為對(duì)象,可以實(shí)現(xiàn)二者之間的松耦合。
Command命令模式的結(jié)構(gòu)如圖8所示。
總結(jié):
(1)Command模式的根本目的在于“行為請(qǐng)求者”與“行為實(shí)現(xiàn)者”解耦,在面向?qū)ο蟮恼Z(yǔ)言中,常見(jiàn)的實(shí)現(xiàn)手段是“將行為抽象為對(duì)象”
(2)實(shí)現(xiàn)Command接口的具體命令對(duì)象ConcreteCommand有時(shí)候根據(jù)需要可能會(huì)保存一些額外的狀態(tài)信息。通過(guò)使用Composite模式,可以將多個(gè)“命令”封裝為一個(gè)“符合命令”MacroCommand
(3)Command模式與C++中的函數(shù)對(duì)像有些類(lèi)似。但兩者定義行為接口的規(guī)范有所區(qū)別:Command以面向?qū)ο笾械摹敖涌?實(shí)現(xiàn)”來(lái)定義行為接口規(guī)范,更嚴(yán)格,但有性能損失;C++函數(shù)對(duì)象以函數(shù)簽名來(lái)定義行為接口規(guī)范,更靈活,性能能高。
9、Visitor訪問(wèn)器
Visitor訪問(wèn)器模式定義:表示一個(gè)作用與某對(duì)像結(jié)構(gòu)中的各元素的操作。使得可以在不改變(穩(wěn)定)各元素的類(lèi)的前提下定義(擴(kuò)展)作用于這些元素的新操作(變化)。
Visitor訪問(wèn)器模式動(dòng)機(jī):在軟件構(gòu)建的過(guò)程中,由于需求的改變,某些類(lèi)層次結(jié)構(gòu)中常常需要增加新的行為(方法)。如果直接在類(lèi)中做這樣的更改,將會(huì)給子類(lèi)帶來(lái)很繁重的變更負(fù)擔(dān),甚至破壞原有設(shè)計(jì)。
如何在不更改類(lèi)層次結(jié)構(gòu)的前提下,在運(yùn)行時(shí)根據(jù)需要透明地為類(lèi)層次結(jié)構(gòu)上的各個(gè)類(lèi)動(dòng)態(tài)添加新的操作,從而避免上述問(wèn)題?
Visitor訪問(wèn)器模式的結(jié)構(gòu)如圖9所示。
總結(jié):
(1)Vistor模式通過(guò)所謂的雙重分發(fā)(double dispatch)來(lái)實(shí)現(xiàn)在不更改(不添加新的操作-編譯時(shí))Element類(lèi)層次結(jié)構(gòu)的前提下,在運(yùn)行時(shí)透明地為類(lèi)層次結(jié)構(gòu)上的各個(gè)類(lèi)動(dòng)態(tài)添加新的操作(支持變化)。
(2)所謂雙重分發(fā)即Vistor模式中間包括了兩個(gè)多態(tài)分發(fā)(注意其中的多態(tài)機(jī)制):第一個(gè)accept方法的多態(tài)解析;第二個(gè)為visitElementX方法的多態(tài)辨析。
(3)Visitor模式最大的缺點(diǎn)在于擴(kuò)展類(lèi)層次結(jié)構(gòu)(增添新的Element子類(lèi)),會(huì)導(dǎo)致Visitor類(lèi)的改變。因此Visitor模式適用于“Element類(lèi)層次結(jié)構(gòu)穩(wěn)定,而其中的操作卻進(jìn)場(chǎng)面臨頻繁改動(dòng)”。
(五)“領(lǐng)域規(guī)則”模式
在特定領(lǐng)域內(nèi),某些變化雖然頻繁,但可以抽象為某種規(guī)則。這時(shí)候,結(jié)合特定領(lǐng)域,將問(wèn)題抽象為語(yǔ)法規(guī)則,從而給出該領(lǐng)域下的一般性解決方案。
典型模式:Interpreter。
10、Interpreter解析器
Interpreter解析器模式定義:給定一個(gè)語(yǔ)言,定義它的文法的一種表示,并定義一種解釋器,這個(gè)解釋器使用該表示來(lái)解釋語(yǔ)言中的句子。
Interpreter解析器模式動(dòng)機(jī):在軟件構(gòu)建過(guò)程中,如果某一特定領(lǐng)域的問(wèn)題比較復(fù)雜,類(lèi)似的結(jié)構(gòu)不斷的重復(fù)出現(xiàn),如果使用普通的變成方式來(lái)實(shí)現(xiàn)將面臨非常頻繁的變化。
在這種情況下,將特定領(lǐng)域的問(wèn)題表達(dá)為某種語(yǔ)法規(guī)則下的句子,然后構(gòu)建一個(gè)解析器來(lái)解釋這樣的句子,從而達(dá)到解決問(wèn)題的目的。
Interpreter解析器模式的結(jié)構(gòu)如圖10所示。
總結(jié):
(1)Interpreter模式的應(yīng)用場(chǎng)合是Interpreter模式應(yīng)用中的難點(diǎn),只有滿(mǎn)足“業(yè)務(wù)規(guī)則頻繁變化,且類(lèi)似的結(jié)構(gòu)不斷重復(fù)出現(xiàn),并且容易抽象為語(yǔ)法規(guī)則的問(wèn)題”才適合使用Interpreter模式。
(2)使用Interpreter模式來(lái)表示文法規(guī)則,從而可以使用面向?qū)ο蠹记蓙?lái)方便地“擴(kuò)展”文法。
(3)Interpreter模式比較適合簡(jiǎn)單的文法表示,對(duì)于復(fù)雜的文法表示,Interpreter模式會(huì)產(chǎn)生比較大的類(lèi)層次結(jié)構(gòu),需要求助于語(yǔ)法分析生成器這樣的標(biāo)準(zhǔn)工具。
設(shè)計(jì)模式總結(jié)
一個(gè)目標(biāo):管理變化,提高復(fù)用。
兩種手段:分解,抽象。
八大原則:依賴(lài)倒置原則(DIP)
? ? ? ? ? ? ? ? ? ? 開(kāi)放封閉原則(OCP)
? ? ? ? ? ? ? ? ? ? 單一職責(zé)原則(SRP)
? ? ? ? ? ? ? ? ? ? Liskov替換原則(LSP)
? ? ? ? ? ? ? ? ? ? 接口隔離原則(ISP)
? ? ? ? ? ? ? ? ? ? 優(yōu)先使用對(duì)象組合,而不是類(lèi)繼承
? ? ? ? ? ? ? ? ? ? 封裝變化點(diǎn)
? ? ? ? ? ? ? ? ? ? 針對(duì)接口編程,而不是針對(duì)實(shí)現(xiàn)編程
重構(gòu)方法:靜態(tài)變?yōu)閯?dòng)態(tài),早綁定變?yōu)橥斫壎ǎ^承變?yōu)榻M合,編譯時(shí)依賴(lài)變?yōu)檫\(yùn)行時(shí)依賴(lài),緊耦合變?yōu)樗神詈稀?/p>
C++對(duì)象模型:
不需要設(shè)計(jì)模式的情況:
(1)代碼可讀性很差時(shí);(2)需求理解很淺時(shí);(3)變化沒(méi)有顯現(xiàn)時(shí);(4)不是系統(tǒng)的關(guān)鍵依賴(lài)點(diǎn)時(shí);(5)項(xiàng)目沒(méi)有復(fù)用價(jià)值時(shí);(6)項(xiàng)目將來(lái)要發(fā)布時(shí)。
設(shè)計(jì)模式經(jīng)驗(yàn):
(1)不要為模式而模式;(2)關(guān)注抽象類(lèi)和接口;(3)理清變化點(diǎn)和穩(wěn)定點(diǎn);(4)審視依賴(lài)關(guān)系;(5)要有Framework和Appliacation的區(qū)隔思維;(6)良好的設(shè)計(jì)是演化的結(jié)果。