設(shè)計(jì)模式之行為型模式
行為型模式用于描述程序在運(yùn)行時(shí)復(fù)雜的流程控制,即描述多個(gè)類或?qū)ο笾g怎樣相互協(xié)作共同完成單個(gè)對象都無法單獨(dú)完成的任務(wù),它涉及算法與對象間職責(zé)的分配。
行為型模式分為類行為模式和對象行為模式,前者采用繼承機(jī)制來在類間分派行為,后者采用組合或聚合在對象間分配行為。由于組合關(guān)系或聚合關(guān)系比繼承關(guān)系耦合度低,滿足“合成復(fù)用原則”,所以對象行為模式比類行為模式具有更大的靈活性。
設(shè)計(jì)模式名稱
簡要說明
模板模式
(Template Pattern)
定義一套流程模板,根據(jù)需要實(shí)現(xiàn)模板中的操作。
策略模式
(Strategy Pattern)
封裝不同的算法,算法之間能互相替換
責(zé)任鏈模式
(Chain of Responsibility Pattern)
攔截的類都實(shí)現(xiàn)統(tǒng)一接口,每個(gè)接收者都包含對下一個(gè)接收者的引用。將這些對象連接成一條鏈,并且沿著這條鏈傳遞請求,直到有對象處理它為止
迭代器模式
(Iterator Pattern)
提供一種方法順序訪問一個(gè)聚合對象中的各個(gè)元素
命令模式
(Command Pattern)
將請求封裝成命令,并記錄下來,能夠撤銷與重做
狀態(tài)模式
(State Pattern)
根據(jù)不同的狀態(tài)做出不同的行為
備忘錄模式
(Memento Pattern)
保存對象的狀態(tài),在需要時(shí)進(jìn)行恢復(fù)
中介者模式
(Mediator Pattern)
將對象之間的通信關(guān)聯(lián)關(guān)系封裝到一個(gè)中介類中單獨(dú)處理,從而使其耦合松散
解釋器模式
(Interpreter Pattern)
給定一個(gè)語言,定義它的語法表示,并定義一個(gè)解釋器,這個(gè)解釋器使用該標(biāo)識來解釋語言中的句子
觀察者模式
(Observer Pattern)
狀態(tài)發(fā)生改變時(shí)通知觀察者,一對多的關(guān)系
訪問者模式
(Visitor Pattern)
穩(wěn)定數(shù)據(jù)結(jié)構(gòu),定義新的操作行為
委派模式
(Delegate Pattern)
允許對象組合實(shí)現(xiàn)與繼承相同的代碼重用,負(fù)責(zé)任務(wù)的調(diào)用和分配
模板方法模式
1、概述:
定義一個(gè)操作中的算法骨架,而將算法的一些步驟延遲到子類中,使得子類可以不改變該算法結(jié)構(gòu)的情況下重定義該算法的某些特定步驟。它是一種類行為型模式。
2、主要角色:
①、抽象類/抽象模板(Abstract Class)抽象模板類,負(fù)責(zé)給出一個(gè)算法的輪廓和骨架。它由一個(gè)模板方法和若干個(gè)基本方法構(gòu)成。
②、具體子類/具體實(shí)現(xiàn)(Concrete Class)具體實(shí)現(xiàn)類,實(shí)現(xiàn)抽象類中所定義的抽象方法和鉤子方法,它們是一個(gè)頂級邏輯的一個(gè)組成步驟。
3、應(yīng)用場景:
①、算法的整體步驟很固定,但其中個(gè)別部分易變時(shí),這時(shí)候可以使用模板方法模式,將容易變的部分抽象出來,供子類實(shí)現(xiàn)。
②、當(dāng)多個(gè)子類存在公共的行為時(shí),可以將其提取出來并集中到一個(gè)公共父類中以避免代碼重復(fù)。首先,要識別現(xiàn)有代碼中的不同之處,并且將不同之處分離為新的操作。最后,用一個(gè)調(diào)用這些新的操作的模板方法來替換這些不同的代碼。
③、當(dāng)需要控制子類的擴(kuò)展時(shí),模板方法只在特定點(diǎn)調(diào)用鉤子操作,這樣就只允許在這些點(diǎn)進(jìn)行擴(kuò)展。
4、優(yōu)點(diǎn):
①、它封裝了不變部分,擴(kuò)展可變部分。它把認(rèn)為是不變部分的算法封裝到父類中實(shí)現(xiàn),而把可變部分算法由子類繼承實(shí)現(xiàn),便于子類繼續(xù)擴(kuò)展。
②、它在父類中提取了公共的部分代碼,便于代碼復(fù)用。
部分方法是由子類實(shí)現(xiàn)的,因此子類可以通過擴(kuò)展方式增加相應(yīng)的功能,符合開閉原則。
5、缺點(diǎn):
①、對每個(gè)不同的實(shí)現(xiàn)都需要定義一個(gè)子類,這會(huì)導(dǎo)致類的個(gè)數(shù)增加,系統(tǒng)更加龐大,設(shè)計(jì)也更加抽象,間接地增加了系統(tǒng)實(shí)現(xiàn)的復(fù)雜度。
②、父類中的抽象方法由子類實(shí)現(xiàn),子類執(zhí)行的結(jié)果會(huì)影響父類的結(jié)果,這導(dǎo)致一種反向的控制結(jié)構(gòu),它提高了代碼閱讀的難度。
③、由于繼承關(guān)系自身的缺點(diǎn),如果父類添加新的抽象方法,則所有子類都要改一遍。
策略模式
1、概述:
該模式定義了一系列算法,并將每個(gè)算法封裝起來,使它們可以相互替換,且算法的變化不會(huì)影響使用算法的客戶。策略模式屬于對象行為模式,它通過對算法進(jìn)行封裝,把使用算法的責(zé)任和算法的實(shí)現(xiàn)分割開來,并委派給不同的對象對這些算法進(jìn)行管理。
2、主要角色:
①、抽象策略(Strategy)類:定義了一個(gè)公共接口,各種不同的算法以不同的方式實(shí)現(xiàn)這個(gè)接口,環(huán)境角色使用這個(gè)接口調(diào)用不同的算法,一般使用接口或抽象類實(shí)現(xiàn)。
②、具體策略(Concrete Strategy)類:實(shí)現(xiàn)了抽象策略定義的接口,提供具體的算法實(shí)現(xiàn)。
③、環(huán)境(Context)類:持有一個(gè)策略類的引用,最終給客戶端調(diào)用。
3、應(yīng)用場景:
①、一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種時(shí),可將每個(gè)算法封裝到策略類中。
②、一個(gè)類定義了多種行為,并且這些行為在這個(gè)類的操作中以多個(gè)條件語句的形式出現(xiàn),可將每個(gè)條件分支移入它們各自的策略類中以代替這些條件語句。
③、系統(tǒng)中各算法彼此完全獨(dú)立,且要求對客戶隱藏具體算法的實(shí)現(xiàn)細(xì)節(jié)時(shí)。
系統(tǒng)要求使用算法的客戶不應(yīng)該知道其操作的數(shù)據(jù)時(shí),可使用策略模式來隱藏與算法相關(guān)的數(shù)據(jù)結(jié)構(gòu)。
④、多個(gè)類只區(qū)別在表現(xiàn)行為不同,可以使用策略模式,在運(yùn)行時(shí)動(dòng)態(tài)選擇具體要執(zhí)行的行為。
4、優(yōu)點(diǎn):
①、多重條件語句不易維護(hù),而使用策略模式可以避免使用多重條件語句,如 if...else 語句、switch...case 語句。
②、策略模式提供了一系列的可供重用的算法族,恰當(dāng)使用繼承可以把算法族的公共代碼轉(zhuǎn)移到父類里面,從而避免重復(fù)的代碼。
③、策略模式可以提供相同行為的不同實(shí)現(xiàn),客戶可以根據(jù)不同時(shí)間或空間要求選擇不同的。
④、策略模式提供了對開閉原則的完美支持,可以在不修改原代碼的情況下,靈活增加新算法。
⑤、策略模式把算法的使用放到環(huán)境類中,而算法的實(shí)現(xiàn)移到具體策略類中,實(shí)現(xiàn)了二者的分離。
5、缺點(diǎn):
①、客戶端必須理解所有策略算法的區(qū)別,以便適時(shí)選擇恰當(dāng)?shù)乃惴悺?/p>
②、策略模式造成很多的策略類,增加維護(hù)難度。
命令模式
1、概述:
將一個(gè)請求封裝為一個(gè)對象,使發(fā)出請求的責(zé)任和執(zhí)行請求的責(zé)任分割開。這樣兩者之間通過命令對象進(jìn)行溝通,這樣方便將命令對象進(jìn)行儲(chǔ)存、傳遞、調(diào)用、增加與管理。
2、主要角色:
①、抽象命令類(Command)角色:聲明執(zhí)行命令的接口,擁有執(zhí)行命令的抽象方法 execute()。
②、具體命令類(Concrete Command)角色:是抽象命令類的具體實(shí)現(xiàn)類,它擁有接收者對象,并通過調(diào)用接收者的功能來完成命令要執(zhí)行的操作。
③、實(shí)現(xiàn)者/接收者(Receiver)角色:執(zhí)行命令功能的相關(guān)操作,是具體命令對象業(yè)務(wù)的真正實(shí)現(xiàn)者。
④、調(diào)用者/請求者(Invoker)角色:是請求的發(fā)送者,它通常擁有很多的命令對象,并通過訪問命令對象來執(zhí)行相關(guān)請求,它不直接訪問接收者。
3、應(yīng)用場景:
①、請求調(diào)用者需要與請求接收者解耦時(shí),命令模式可以使調(diào)用者和接收者不直接交互。
②、系統(tǒng)隨機(jī)請求命令或經(jīng)常增加、刪除命令時(shí),命令模式可以方便地實(shí)現(xiàn)這些功能。
③、當(dāng)系統(tǒng)需要執(zhí)行一組操作時(shí),命令模式可以定義宏命令來實(shí)現(xiàn)該功能。
④、當(dāng)系統(tǒng)需要支持命令的撤銷(Undo)操作和恢復(fù)(Redo)操作時(shí),可以將命令對象存儲(chǔ)起來,采用備忘錄模式來實(shí)現(xiàn)。
4、優(yōu)點(diǎn):
①、通過引入中間件(抽象接口)降低系統(tǒng)的耦合度。
②、擴(kuò)展性良好,增加或刪除命令非常方便。采用命令模式增加與刪除命令不會(huì)影響其他類,且滿足“開閉原則”。
③、可以實(shí)現(xiàn)宏命令。命令模式可以與組合模式結(jié)合,將多個(gè)命令裝配成一個(gè)組合命令,即宏命令。
④、方便實(shí)現(xiàn) Undo 和 Redo 操作。命令模式可以與后面介紹的備忘錄模式結(jié)合,實(shí)現(xiàn)命令的撤銷與恢復(fù)。
⑤、可以在現(xiàn)有命令的基礎(chǔ)上,增加額外功能。比如日志記錄,結(jié)合裝飾器模式會(huì)更加靈活。
5、缺點(diǎn):
①、可能產(chǎn)生大量具體的命令類。因?yàn)槊恳粋€(gè)具體操作都需要設(shè)計(jì)一個(gè)具體命令類,這會(huì)增加系統(tǒng)的復(fù)雜性。
②、命令模式的結(jié)果其實(shí)就是接收方的執(zhí)行結(jié)果,但是為了以命令的形式進(jìn)行架構(gòu)、解耦請求與實(shí)現(xiàn),引入了額外類型結(jié)構(gòu)(引入了請求方與抽象命令接口),增加了理解上的困難。不過這也是設(shè)計(jì)模式的通病,抽象必然會(huì)額外增加類的數(shù)量,代碼抽離肯定比代碼聚合更加難理解。
責(zé)任鏈模式
1、概述:
為了避免請求發(fā)送者與多個(gè)請求處理者耦合在一起,于是將所有請求的處理者通過前一對象記住其下一個(gè)對象的引用而連成一條鏈;當(dāng)有請求發(fā)生時(shí),可將請求沿著這條鏈傳遞,直到有對象處理它為止。注意:責(zé)任鏈模式也叫職責(zé)鏈模式。
2、主要角色:
①、抽象處理者(Handler)角色:定義一個(gè)處理請求的接口,包含抽象處理方法和一個(gè)后繼連接。
②、具體處理者(Concrete Handler)角色:實(shí)現(xiàn)抽象處理者的處理方法,判斷能否處理本次請求,如果可以處理請求則處理,否則將該請求轉(zhuǎn)給它的后繼者。
③、客戶類(Client)角色:創(chuàng)建處理鏈,并向鏈頭的具體處理者對象提交請求,它不關(guān)心處理細(xì)節(jié)和請求的傳遞過程。
3、應(yīng)用場景:
①、多個(gè)對象可以處理一個(gè)請求,但具體由哪個(gè)對象處理該請求在運(yùn)行時(shí)自動(dòng)確定。
②、可動(dòng)態(tài)指定一組對象處理請求,或添加新的處理者。
③、需要在不明確指定請求處理者的情況下,向多個(gè)處理者中的一個(gè)提交請求。
4、優(yōu)點(diǎn):
①、降低了對象之間的耦合度。該模式使得一個(gè)對象無須知道到底是哪一個(gè)對象處理其請求以及鏈的結(jié)構(gòu),發(fā)送者和接收者也無須擁有對方的明確信息。
②、增強(qiáng)了系統(tǒng)的可擴(kuò)展性。可以根據(jù)需要增加新的請求處理類,滿足開閉原則。
③、增強(qiáng)了給對象指派職責(zé)的靈活性。當(dāng)工作流程發(fā)生變化,可以動(dòng)態(tài)地改變鏈內(nèi)的成員或者調(diào)動(dòng)它們的次序,也可動(dòng)態(tài)地新增或者刪除責(zé)任。
④、責(zé)任鏈簡化了對象之間的連接。每個(gè)對象只需保持一個(gè)指向其后繼者的引用,不需保持其他所有處理者的引用,這避免了使用眾多的 if 或者 if···else 語句。
⑤、責(zé)任分擔(dān)。每個(gè)類只需要處理自己該處理的工作,不該處理的傳遞給下一個(gè)對象完成,明確各類的責(zé)任范圍,符合類的單一職責(zé)原則。
5、缺點(diǎn):
①、不能保證每個(gè)請求一定被處理。由于一個(gè)請求沒有明確的接收者,所以不能保證它一定會(huì)被處理,該請求可能一直傳到鏈的末端都得不到處理。
②、對比較長的職責(zé)鏈,請求的處理可能涉及多個(gè)處理對象,系統(tǒng)性能將受到一定影響。
③、職責(zé)鏈建立的合理性要靠客戶端來保證,增加了客戶端的復(fù)雜性,可能會(huì)由于職責(zé)鏈的錯(cuò)誤設(shè)置而導(dǎo)致系統(tǒng)出錯(cuò),如可能會(huì)造成循環(huán)調(diào)用。
狀態(tài)模式
1、概述:
對有狀態(tài)的對象,把復(fù)雜的“判斷邏輯”提取到不同的狀態(tài)對象中,允許狀態(tài)對象在其內(nèi)部狀態(tài)發(fā)生改變時(shí)改變其行為。
2、主要角色:
①、環(huán)境類(Context)角色:也稱為上下文,它定義了客戶端需要的接口,內(nèi)部維護(hù)一個(gè)當(dāng)前狀態(tài),并負(fù)責(zé)具體狀態(tài)的切換。
②、抽象狀態(tài)(State)角色:定義一個(gè)接口,用以封裝環(huán)境對象中的特定狀態(tài)所對應(yīng)的行為,可以有一個(gè)或多個(gè)行為。
③、具體狀態(tài)(Concrete State)角色:實(shí)現(xiàn)抽象狀態(tài)所對應(yīng)的行為,并且在需要的情況下進(jìn)行狀態(tài)切換。
3、應(yīng)用場景:
①、當(dāng)一個(gè)對象的行為取決于它的狀態(tài),并且它必須在運(yùn)行時(shí)根據(jù)狀態(tài)改變它的行為時(shí),就可以考慮使用狀態(tài)模式。
②、一個(gè)操作中含有龐大的分支結(jié)構(gòu),并且這些分支決定于對象的狀態(tài)時(shí)。
4、優(yōu)點(diǎn):
①、結(jié)構(gòu)清晰,狀態(tài)模式將與特定狀態(tài)相關(guān)的行為局部化到一個(gè)狀態(tài)中,并且將
②、不同狀態(tài)的行為分割開來,滿足“單一職責(zé)原則”。
③、將狀態(tài)轉(zhuǎn)換顯示化,減少對象間的相互依賴。將不同的狀態(tài)引入獨(dú)立的對象中會(huì)使得狀態(tài)轉(zhuǎn)換變得更加明確,且減少對象間的相互依賴。
④、狀態(tài)類職責(zé)明確,有利于程序的擴(kuò)展。通過定義新的子類很容易地增加新的狀態(tài)和轉(zhuǎn)換。
5、缺點(diǎn):
①、狀態(tài)模式的使用必然會(huì)增加系統(tǒng)的類與對象的個(gè)數(shù)。
②、狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)都較為復(fù)雜,如果使用不當(dāng)會(huì)導(dǎo)致程序結(jié)構(gòu)和代碼的混亂。
③、狀態(tài)模式對開閉原則的支持并不太好,對于可以切換狀態(tài)的狀態(tài)模式,增加新的狀態(tài)類需要修改那些負(fù)責(zé)狀態(tài)轉(zhuǎn)換的源碼,否則無法切換到新增狀態(tài),而且修改某個(gè)狀態(tài)類的行為也需要修改對應(yīng)類的源碼。
觀察者模式
1、概述:
指多個(gè)對象間存在一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對象都得到通知并被自動(dòng)更新。這種模式有時(shí)又稱作發(fā)布-訂閱模式、模型-視圖模式,它是對象行為型模式。
2、主要角色:
①、抽象主題(Subject)角色:也叫抽象目標(biāo)類,它提供了一個(gè)用于保存觀察者對象的聚集類和增加、刪除觀察者對象的方法,以及通知所有觀察者的抽象方法。
②、具體主題(Concrete Subject)角色:也叫具體目標(biāo)類,它實(shí)現(xiàn)抽象目標(biāo)中的通知方法,當(dāng)具體主題的內(nèi)部狀態(tài)發(fā)生改變時(shí),通知所有注冊過的觀察者對象。
③、抽象觀察者(Observer)角色:它是一個(gè)抽象類或接口,它包含了一個(gè)更新自己的抽象方法,當(dāng)接到具體主題的更改通知時(shí)被調(diào)用。
④、具體觀察者(Concrete Observer)角色:實(shí)現(xiàn)抽象觀察者中定義的抽象方法,以便在得到目標(biāo)的更改通知時(shí)更新自身的狀態(tài)。
3、應(yīng)用場景:
①、對象間存在一對多關(guān)系,一個(gè)對象的狀態(tài)發(fā)生改變會(huì)影響其他對象。
②、當(dāng)一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴于另一方面時(shí),可將這二者封裝在獨(dú)立的對象中以使它們可以各自獨(dú)立地改變和復(fù)用。
③、實(shí)現(xiàn)類似廣播機(jī)制的功能,不需要知道具體收聽者,只需分發(fā)廣播,系統(tǒng)中感興趣的對象會(huì)自動(dòng)接收該廣播。
④、多層級嵌套使用,形成一種鏈?zhǔn)接|發(fā)機(jī)制,使得事件具備跨域(跨越兩種觀察者類型)通知。
4、優(yōu)點(diǎn):
①、降低了目標(biāo)與觀察者之間的耦合關(guān)系,兩者之間是抽象耦合關(guān)系。符合依賴倒置原則。
②、目標(biāo)與觀察者之間建立了一套觸發(fā)機(jī)制。
5、缺點(diǎn):
①、目標(biāo)與觀察者之間的依賴關(guān)系并沒有完全解除,而且有可能出現(xiàn)循環(huán)引用。
②、當(dāng)觀察者對象很多時(shí),通知的發(fā)布會(huì)花費(fèi)很多時(shí)間,影響程序的效率。
中介者模式
1、概述:
定義一個(gè)中介對象來封裝一系列對象之間的交互,使原有對象之間的耦合松散,且可以獨(dú)立地改變它們之間的交互。中介者模式又叫調(diào)停模式,它是迪米特法則的典型應(yīng)用。
2、主要角色:
①、抽象中介者(Mediator)角色:它是中介者的接口,提供了同事對象注冊與轉(zhuǎn)發(fā)同事對象信息的抽象方法。
②、具體中介者(Concrete Mediator)角色:實(shí)現(xiàn)中介者接口,定義一個(gè) List 來管理同事對象,協(xié)調(diào)各個(gè)同事角色之間的交互關(guān)系,因此它依賴于同事角色。
③、抽象同事類(Colleague)角色:定義同事類的接口,保存中介者對象,提供同事對象交互的抽象方法,實(shí)現(xiàn)所有相互影響的同事類的公共功能。
④、具體同事類(Concrete Colleague)角色:是抽象同事類的實(shí)現(xiàn)者,當(dāng)需要與其他同事對象交互時(shí),由中介者對象負(fù)責(zé)后續(xù)的交互。
3、應(yīng)用場景:
①、當(dāng)對象之間存在復(fù)雜的網(wǎng)狀結(jié)構(gòu)關(guān)系而導(dǎo)致依賴關(guān)系混亂且難以復(fù)用時(shí)。
②、當(dāng)想創(chuàng)建一個(gè)運(yùn)行于多個(gè)類之間的對象,又不想生成新的子類時(shí)。
4、優(yōu)點(diǎn):
①、類之間各司其職,符合迪米特法則。
②、降低了對象之間的耦合性,使得對象易于獨(dú)立地被復(fù)用。
③、將對象間的一對多關(guān)聯(lián)轉(zhuǎn)變?yōu)橐粚σ坏年P(guān)聯(lián),提高系統(tǒng)的靈活性,使得系統(tǒng)易于維護(hù)和擴(kuò)展。
5、缺點(diǎn):
中介者模式將原本多個(gè)對象直接的相互依賴變成了中介者和多個(gè)同事類的依賴關(guān)系。當(dāng)同事類越多時(shí),中介者就會(huì)越臃腫,變得復(fù)雜且難以維護(hù)。
迭代器模式
1、概述:
提供一個(gè)對象來順序訪問聚合對象中的一系列數(shù)據(jù),而不暴露聚合對象的內(nèi)部表示。迭代器模式是一種對象行為型模式,其主要優(yōu)點(diǎn)如下。
2、主要角色:
①、抽象聚合(Aggregate)角色:定義存儲(chǔ)、添加、刪除聚合對象以及創(chuàng)建迭代器對象的接口。
②、具體聚合(ConcreteAggregate)角色:實(shí)現(xiàn)抽象聚合類,返回一個(gè)具體迭代器的實(shí)例。
③、抽象迭代器(Iterator)角色:定義訪問和遍歷聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。
④、具體迭代器(Concretelterator)角色:實(shí)現(xiàn)抽象迭代器接口中所定義的方法,完成對聚合對象的遍歷,記錄遍歷的當(dāng)前位置。
3、應(yīng)用場景:
①、當(dāng)需要為聚合對象提供多種遍歷方式時(shí)。
②、當(dāng)需要為遍歷不同的聚合結(jié)構(gòu)提供一個(gè)統(tǒng)一的接口時(shí)。
③、當(dāng)訪問一個(gè)聚合對象的內(nèi)容而無須暴露其內(nèi)部細(xì)節(jié)的表示時(shí)。
4、優(yōu)點(diǎn):
①、訪問一個(gè)聚合對象的內(nèi)容而無須暴露它的內(nèi)部表示。
②、遍歷任務(wù)交由迭代器完成,這簡化了聚合類。
③、它支持以不同方式遍歷一個(gè)聚合,甚至可以自定義迭代器的子類以支持新的遍歷。
④、增加新的聚合類和迭代器類都很方便,無須修改原有代碼。
封裝性良好,為遍歷不同的聚合結(jié)構(gòu)提供一個(gè)統(tǒng)一的接口。
5、缺點(diǎn):
增加了類的個(gè)數(shù),這在一定程度上增加了系統(tǒng)的復(fù)雜性。
訪問者模式
1、概述:
將作用于某種數(shù)據(jù)結(jié)構(gòu)中的各元素的操作分離出來封裝成獨(dú)立的類,使其在不改變數(shù)據(jù)結(jié)構(gòu)的前提下可以添加作用于這些元素的新的操作,為數(shù)據(jù)結(jié)構(gòu)中的每個(gè)元素提供多種訪問方式。它將對數(shù)據(jù)的操作與數(shù)據(jù)結(jié)構(gòu)進(jìn)行分離,是行為類模式中最復(fù)雜的一種模式。
2、主要角色:
①、抽象訪問者(Visitor)角色:定義一個(gè)訪問具體元素的接口,為每個(gè)具體元素類對應(yīng)一個(gè)訪問操作 visit() ,該操作中的參數(shù)類型標(biāo)識了被訪問的具體元素。
②、具體訪問者(ConcreteVisitor)角色:實(shí)現(xiàn)抽象訪問者角色中聲明的各個(gè)訪問操作,確定訪問者訪問一個(gè)元素時(shí)該做什么。
③、抽象元素(Element)角色:聲明一個(gè)包含接受操作 accept() 的接口,被接受的訪問者對象作為 accept() 方法的參數(shù)。
④、具體元素(ConcreteElement)角色:實(shí)現(xiàn)抽象元素角色提供的 accept() 操作,其方法體通常都是 visitor.visit(this) ,另外具體元素中可能還包含本身業(yè)務(wù)邏輯的相關(guān)操作。
⑤、對象結(jié)構(gòu)(Object Structure)角色:是一個(gè)包含元素角色的容器,提供讓訪問者對象遍歷容器中的所有元素的方法,通常由 List、Set、Map 等聚合類實(shí)現(xiàn)。
3、應(yīng)用場景:
①、對象結(jié)構(gòu)相對穩(wěn)定,但其操作算法經(jīng)常變化的程序。
②、對象結(jié)構(gòu)中的對象需要提供多種不同且不相關(guān)的操作,而且要避免讓這些操作的變化影響對象的結(jié)構(gòu)。
③、對象結(jié)構(gòu)包含很多類型的對象,希望對這些對象實(shí)施一些依賴于其具體類型的操作。
4、優(yōu)點(diǎn):
①、擴(kuò)展性好。能夠在不修改對象結(jié)構(gòu)中的元素的情況下,為對象結(jié)構(gòu)中的元素添加新的功能。
②、復(fù)用性好。可以通過訪問者來定義整個(gè)對象結(jié)構(gòu)通用的功能,從而提高系統(tǒng)的復(fù)用程度。
③、靈活性好。訪問者模式將數(shù)據(jù)結(jié)構(gòu)與作用于結(jié)構(gòu)上的操作解耦,使得操作集合可相對自由地演化而不影響系統(tǒng)的數(shù)據(jù)結(jié)構(gòu)。
④、符合單一職責(zé)原則。訪問者模式把相關(guān)的行為封裝在一起,構(gòu)成一個(gè)訪問者,使每一個(gè)訪問者的功能都比較單一。
5、缺點(diǎn):
①、增加新的元素類很困難。在訪問者模式中,每增加一個(gè)新的元素類,都要在每一個(gè)具體訪問者類中增加相應(yīng)的具體操作,這違背了“開閉原則”。
②、破壞封裝。訪問者模式中具體元素對訪問者公布細(xì)節(jié),這破壞了對象的封裝性。
③、違反了依賴倒置原則。訪問者模式依賴了具體類,而沒有依賴抽象類。
備忘錄模式
1、概述:
在不破壞封裝性的前提下,捕獲一個(gè)對象的內(nèi)部狀態(tài),并在該對象之外保存這個(gè)狀態(tài),以便以后當(dāng)需要時(shí)能將該對象恢復(fù)到原先保存的狀態(tài)。該模式又叫快照模式。
2、主要角色:
①、發(fā)起人(Originator)角色:記錄當(dāng)前時(shí)刻的內(nèi)部狀態(tài)信息,提供創(chuàng)建備忘錄和恢復(fù)備忘錄數(shù)據(jù)的功能,實(shí)現(xiàn)其他業(yè)務(wù)功能,它可以訪問備忘錄里的所有信息。
②、備忘錄(Memento)角色:負(fù)責(zé)存儲(chǔ)發(fā)起人的內(nèi)部狀態(tài),在需要的時(shí)候提供這些內(nèi)部狀態(tài)給發(fā)起人。
③、管理者(Caretaker)角色:對備忘錄進(jìn)行管理,提供保存與獲取備忘錄的功能,但其不能對備忘錄的內(nèi)容進(jìn)行訪問與修改。
3、應(yīng)用場景:
①、需要保存與恢復(fù)數(shù)據(jù)的場景,如玩游戲時(shí)的中間結(jié)果的存檔功能。
②、需要提供一個(gè)可回滾操作的場景,如 Word、記事本、Photoshop,Eclipse 等軟件在編輯時(shí)按 Ctrl+Z 組合鍵,還有數(shù)據(jù)庫中事務(wù)操作。
4、優(yōu)點(diǎn):
①、提供了一種可以恢復(fù)狀態(tài)的機(jī)制。當(dāng)用戶需要時(shí)能夠比較方便地將數(shù)據(jù)恢復(fù)到某個(gè)歷史的狀態(tài)。
②、實(shí)現(xiàn)了內(nèi)部狀態(tài)的封裝。除了創(chuàng)建它的發(fā)起人之外,其他對象都不能夠訪問這些狀態(tài)信息。
③、簡化了發(fā)起人類。發(fā)起人不需要管理和保存其內(nèi)部狀態(tài)的各個(gè)備份,所有狀態(tài)信息都保存在備忘錄中,并由管理者進(jìn)行管理,這符合單一職責(zé)原則。
5、缺點(diǎn):
資源消耗大。如果要保存的內(nèi)部狀態(tài)信息過多或者特別頻繁,將會(huì)占用比較大的內(nèi)存資源。
解釋器模式
1、概述:
給分析對象定義一個(gè)語言,并定義該語言的文法表示,再設(shè)計(jì)一個(gè)解析器來解釋語言中的句子。也就是說,用編譯語言的方式來分析應(yīng)用中的實(shí)例。這種模式實(shí)現(xiàn)了文法表達(dá)式處理的接口,該接口解釋一個(gè)特定的上下文。
2、主要角色:
①、抽象表達(dá)式(Abstract Expression)角色:定義解釋器的接口,約定解釋器的解釋操作,主要包含解釋方法 interpret()。
②、終結(jié)符表達(dá)式(Terminal?Expression)角色:是抽象表達(dá)式的子類,用來實(shí)現(xiàn)文法中與終結(jié)符相關(guān)的操作,文法中的每一個(gè)終結(jié)符都有一個(gè)具體終結(jié)表達(dá)式與之相對應(yīng)。
③、非終結(jié)符表達(dá)式(Nonterminal Expression)角色:也是抽象表達(dá)式的子類,用來實(shí)現(xiàn)文法中與非終結(jié)符相關(guān)的操作,文法中的每條規(guī)則都對應(yīng)于一個(gè)非終結(jié)符表達(dá)式。
④、環(huán)境(Context)角色:通常包含各個(gè)解釋器需要的數(shù)據(jù)或是公共的功能,一般用來傳遞被所有解釋器共享的數(shù)據(jù),后面的解釋器可以從這里獲取這些值。
⑤、客戶端(Client):主要任務(wù)是將需要分析的句子或表達(dá)式轉(zhuǎn)換成使用解釋器對象描述的抽象語法樹,然后調(diào)用解釋器的解釋方法,當(dāng)然也可以通過環(huán)境角色間接訪問解釋器的解釋方法。
3、應(yīng)用場景:
①、當(dāng)語言的文法較為簡單,且執(zhí)行效率不是關(guān)鍵問題時(shí)。
②、當(dāng)問題重復(fù)出現(xiàn),且可以用一種簡單的語言來進(jìn)行表達(dá)時(shí)。
③、當(dāng)一個(gè)語言需要解釋執(zhí)行,并且語言中的句子可以表示為一個(gè)抽象語法樹的時(shí)候,如 XML 文檔解釋。
4、優(yōu)點(diǎn):
①、擴(kuò)展性好。由于在解釋器模式中使用類來表示語言的文法規(guī)則,因此可以通過繼承等機(jī)制來改變或擴(kuò)展文法。
②、容易實(shí)現(xiàn)。在語法樹中的每個(gè)表達(dá)式節(jié)點(diǎn)類都是相似的,所以實(shí)現(xiàn)其文法較為容易。
5、缺點(diǎn):
①、執(zhí)行效率較低。解釋器模式中通常使用大量的循環(huán)和遞歸調(diào)用,當(dāng)要解釋的句子較復(fù)雜時(shí),其運(yùn)行速度很慢,且代碼的調(diào)試過程也比較麻煩。
②、會(huì)引起類膨脹。解釋器模式中的每條規(guī)則至少需要定義一個(gè)類,當(dāng)包含的文法規(guī)則很多時(shí),類的個(gè)數(shù)將急劇增加,導(dǎo)致系統(tǒng)難以管理與維護(hù)。
③、可應(yīng)用的場景比較少。在軟件開發(fā)中,需要定義語言文法的應(yīng)用實(shí)例非常少,所以這種模式很少被使用到。
設(shè)計(jì)模式之設(shè)計(jì)原則
設(shè)計(jì)模式之創(chuàng)建型模式
設(shè)計(jì)模式之結(jié)構(gòu)型模式
數(shù)據(jù)結(jié)構(gòu)
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。