設計模式(設計模式概念)

設計模式(設計模式概念)

本詞條是多義詞,共2個義項
更多義項 ▼ 收起列表 ▲

設計模式(Design Pattern)是一套被反覆使用、多數人知曉的、經過分類的、代碼設計經驗的總結。

使用設計模式的目的:為了代碼可重用性、讓代碼更容易被他人理解、保證代碼可靠性。 設計模式使代碼編寫真正工程化;設計模式是軟體工程的基石脈絡,如同大廈的結構一樣。

基本介紹

  • 中文名:設計模式
  • 外文名:Design pattern
  • 提出者:GOF
  • 四要素:模式名稱、問題、解決方案、效果
  • 基本模式:工廠模式、建造者模式、單例模式
簡介,設計框架,設計原則,開閉原則,里氏代換原則,依賴倒轉原則,接口隔離原則,合成/聚合復用,最少知識原則,綜述,模式名稱,問題,解決方案,效果,基本模式,綜述,工廠模式,抽象工廠模式,建造者模式,原型模式,單例模式,適配器模式,橋接模式,組合模式,裝飾模式,門面模式,享元模式,代理模式,職責鏈模式,命令模式,解析器模式,疊代器模式,中介模式,備忘錄模式,觀察者模式,狀態模式,策略模式,模版模式,訪問者模式,設計步驟,綜述,通信和培訓,設計模式指導,架構中的設計,設計模式與重構,四人組,相關圖書,

簡介

設計模式(Design pattern)代表了最佳的實踐,通常被有經驗的面向對象的軟體開發人員所採用。設計模式是軟體開發人員在軟體開發過程中面臨的一般問題的解決方案。這些解決方案是眾多軟體開發人員經過相當長的一段時間的試驗和錯誤總結出來的。
設計模式是一套被反覆使用的、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 毫無疑問,設計模式於己於他人於系統都是多贏的,設計模式使代碼編制真正工程化,設計模式是軟體工程的基石,如同大廈的一塊塊磚石一樣。項目中合理地運用設計模式可以完美地解決很多問題,每種模式在現實中都有相應的原理來與之對應,每種模式都描述了一個在我們周圍不斷重複發生的問題,以及該問題的核心解決方案,這也是設計模式能被廣泛套用的原因。

設計框架

可復用面向對象軟體系統一般劃分為兩大類:應用程式工具箱和框架(Framework),我們平時開發的具體軟體都是應用程式,Java的API屬於工具箱;而框架是構成一類特定軟體可復用設計的一組相互協作的類,EJB(EnterpriseJavaBeans)是Java套用於企業計算的框架。
框架通常定義了套用體系的整體結構類和對象的關係等等設計參數,以便於具體套用實現者能集中精力於套用本身的特定細節。框架主要記錄軟體套用中共同的設計決策,框架強調設計復用,因此框架設計中必然要使用設計模式。
另外,設計模式有助於對框架結構的理解,成熟的框架通常使用了多種設計模式,如果你熟悉這些設計模式,毫無疑問,你將迅速掌握框架的結構,我們一般開發者如果突然接觸EJBSpring等框架,會覺得特別難學、難掌握,那么轉而先掌握設計模式,無疑是給了你剖析EJB或J2EE系統的一把利器

設計原則

為什麼要提倡“Design Pattern呢?根本原因是為了代碼復用,增加可維護性。那么怎么才能實現代碼復用呢?面向對象有幾個原則:單一職責原則 (Single Responsiblity Principle SRP)開閉原則(Open Closed Principle,OCP)、里氏代換原則(Liskov Substitution Principle,LSP)、依賴倒轉原則(Dependency Inversion Principle,DIP)、接口隔離原則(Interface Segregation Principle,ISP)、合成/聚合復用原則(Composite/Aggregate Reuse Principle,CARP)、最小知識原則(Principle of Least Knowledge,PLK,也叫迪米特法則)。開閉原則具有理想主義的色彩,它是面向對象設計的終極目標。其他幾條,則可以看做是開閉原則的實現方法。
設計模式就是實現了這些原則,從而達到了代碼復用、增加可維護性的目的。

開閉原則

此原則是由Bertrand Meyer提出的。原文是:“Software entities should be open for extension,but closed for modification”。就是說模組應對擴展開放,而對修改關閉。模組應儘量在不修改原(是“原”,指原來的代碼)代碼的情況下進行擴展。那么怎么擴展呢?我們看工廠模式“factory pattern”:假設中關村有一個賣盜版盤的小子,我們給他設計一“光碟銷售管理軟體”。我們應該先設計一“光碟”接口。如圖:
[pre]
______________
|<>|
| 光碟 |
|_____________|
|+賣() |
| |
|_____________|
[/pre]
而盜版盤和毛片是其子類。小子通過“DiscFactory”來管理這些光碟。代碼為:
public class DiscFactory{public static 光碟getDisc(Stringname){        return(光碟)Class.forName(name).newInstance();    }}
有人要買盜版盤,怎么實現呢?
public class 小子{public static void main(String[] args){光碟 d = DiscFactory.getDisc("盜版盤");d.賣();}}
如果有一天,這小子良心發現了,開始賣正版軟體。沒關係,我們只要再創建一個“光碟”的子類“正版軟體”就可以了,不需要修改原結構和代碼。怎么樣?對擴展開放,對修改關閉——“開閉原則”。
工廠模式是對具體產品進行擴展,有的項目可能需要更多的擴展性,要對這個“工廠”也進行擴展,那就成了“抽象工廠模式”。

里氏代換原則

里氏代換原則是由Barbara Liskov提出的。如果調用的是父類的話,那么換成子類也完全可以運行。比如:
光碟 d = new 盜版盤();d.賣();
要將“盜版盤”類改為“毛片”類,沒問題,完全可以運行。Java編譯程式會檢查程式是否符合里氏代換原則。還記得java繼承的一個原則嗎?子類override方法的訪問許可權不能小於父類對應方法的訪問許可權。比如“光碟”中的方法“賣”訪問許可權是“public”,那么“盜版盤”和“毛片”中的“賣”方法就不能是protected或private,編譯不能通過。為什麼要這樣呢?你想啊:如果“盜版盤”的“賣”方法是private。那么下面這段代碼就不能執行了:
光碟 d = new 盜版盤();d.賣();
可以說:里氏代換原則是繼承復用的一個基礎。

依賴倒轉原則

指在軟體裡面,把父類都替換成它的子類,程式的行為沒有變化。簡單的說,子類型能夠替換掉它們的父類型。依賴性倒轉其實可以說是面向對象設計的標誌,用哪種語言編程並不是很重要。

接口隔離原則

定製服務的例子,每一個接口應該是一種角色,不多不少,不乾不該幹的事,該幹的事都要乾。

合成/聚合復用

合成/聚合復用原則(Composite/Aggregate Reuse Principle,CARP)經常又叫做合成復用原則。合成/聚合復用原則就是在一個新的對象裡面使用一些已有的對象,使之成為新對象的一部分;新的對象通過向這些對象的委派達到復用已有功能的目的。它的設計原則是:要儘量使用合成/聚合,儘量不要使用繼承。
就是說要少用繼承,多用合成關係來實現。我曾經這樣寫過程式:有幾個類要與資料庫打交道,就寫了一個資料庫操作的類,然後別的跟資料庫打交道的類都繼承這個。結果後來,我修改了資料庫操作類的一個方法,各個類都需要改動。“牽一髮而動全身”!面向對象是要把波動限制在儘量小的範圍。
在Java中,應儘量針對Interface編程,而非實現類。這樣,更換子類不會影響調用它方法的代碼。要讓各個類儘可能少的跟別人聯繫,“不要與陌生人說話”。這樣,城門失火,才不至於殃及池魚。擴展性和維護性才能提高。

最少知識原則

也叫迪米特法則。不要和陌生人說話,即一個對象應對其他對象有儘可能少的了解。

綜述

設計模式使人們可以更加簡單方便地復用成功的設計體系結構。將已證實的技術表述成設計模式也會使新系統開發者更加容易理解其設計思路。

模式名稱

一個助記名,它用一兩個詞來描述模式的問題、解決方案和效果。命名一個新的模式增加了我們的設計辭彙。設計模式允許我們在較高的抽象層次上進行設計。基於一個模式辭彙表,我們自己以及同事之間就可以討論模式並在編寫文檔時使用它們。模式名可以幫助我們思考,便於我們與其他人交流設計思想及設計結果。找到恰當的模式名也是我們設計模式編目工作的難點之一。

問題

描述了應該在何時使用模式。它解釋了設計問題和問題存在的前因後果,它可能描述了特定的設計問題,如怎樣用對象表示算法等。也可能描述了導致不靈活設計的類或對象結構。有時候,問題部分會包括使用模式必須滿足的一系列先決條件。

解決方案

描述了設計的組成成分,它們之間的相互關係及各自的職責和協作方式。因為模式就像一個模板,可套用於多種不同場合,所以解決方案並不描述一個特定而具體的設計或實現,而是提供設計問題的抽象描述和怎樣用一個具有一般意義的元素組合(類或對象組合)來解決這個問題。

效果

描述了模式套用的效果及使用模式應權衡的問題。儘管我們描述設計決策時,並不總提到模式效果,但它們對於評價設計選擇和理解使用模式的代價及好處具有重要意義。軟體效果大多關注對時間和空間的衡量,它們也表述了語言和實現問題。因為復用是面向對象設計的要素之一,所以模式效果包括它對系統的靈活性、擴充性或可移植性的影響,顯式地列出這些效果對理解和評價這些模式很有幫助。

基本模式

綜述

設計模式分為三種類型,共23種。
  • 創建型模式:單例模式、抽象工廠模式、建造者模式、工廠模式、原型模式。
  • 結構型模式:適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。
  • 行為型模式:模版方法模式、命令模式、疊代器模式觀察者模式、中介者模式、備忘錄模式、解釋器模式(Interpreter模式)、狀態模式、策略模式、職責鏈模式(責任鏈模式)、訪問者模式。
按字典序排列簡介如下。
Abstract Factory(抽象工廠模式):提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
Adapter(適配器模式):將一個類的接口轉換成客戶希望的另外一個接口。Adapter模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。
Bridge(橋接模式):將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
Builder(建造者模式):將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
Chain of Responsibility(責任鏈模式):為解除請求的傳送者和接收者之間耦合,而使多個對象都有機會處理這個請求。將這些對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個對象處理它。
Command(命令模式):將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可取消的操作。
Composite(組合模式):將對象組合成樹形結構以表示“部分-整體”的層次結構。它使得客戶對單個對象和複合對象的使用具有一致性。
Decorator(裝飾模式):動態地給一個對象添加一些額外的職責。就擴展功能而言, 它比生成子類方式更為靈活。
Facade(外觀模式):為子系統中的一組接口提供一個一致的界面,Facade模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
Factory Method(工廠模式):定義一個用於創建對象的接口,讓子類決定將哪一個類實例化。Factory Method使一個類的實例化延遲到其子類。
Flyweight(享元模式):運用共享技術有效地支持大量細粒度的對象。
Interpreter(解析器模式):給定一個語言, 定義它的文法的一種表示,並定義一個解釋器, 該解釋器使用該表示來解釋語言中的句子。
Iterator(疊代器模式):提供一種方法順序訪問一個聚合對象中各個元素,而又不需暴露該對象的內部表示。
Mediator(中介模式):用一個中介對象來封裝一系列的對象互動。中介者使各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。
Memento(備忘錄模式):在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到保存的狀態。
Observer(觀察者模式):定義對象間的一種一對多的依賴關係,以便當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並自動刷新。
Prototype(原型模式):用原型實例指定創建對象的種類,並且通過拷貝這個原型來創建新的對象。
Proxy(代理模式):為其他對象提供一個代理以控制對這個對象的訪問。
Singleton(單例模式):保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。 單例模式是最簡單的設計模式之一,但是對於Java的開發者來說,它卻有很多缺陷。在九月的專欄中,David Geary探討了單例模式以及在面對多執行緒(multi-threading)、類裝載器(class loaders)和序列化(serialization)時如何處理這些缺陷。
State(狀態模式):允許一個對象在其內部狀態改變時改變它的行為。對象看起來似乎修改了它所屬的類。
Strategy(策略模式):定義一系列的算法,把它們一個個封裝起來, 並且使它們可相互替換。本模式使得算法的變化可獨立於使用它的客戶。
Template Method(模板方法模式):定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。
Visitor(訪問者模式):表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。
從下一節開始,詳細描述以下每一種設計模式。

工廠模式

意圖
工廠模式(Factory)工廠模式(Factory)
定義一個用於創建對象的接口,讓子類決定實例化哪一個類。Factory Method 使一個類的實例化延遲到其子類。
適用性
  • 當一個類不知道它所必須創建的對象的類的時候。
  • 當一個類希望由它的子類來指定它所創建的對象的時候。
  • 當類將創建對象的職責委託給多個幫助子類中的某一個,並且你希望將哪一個幫助子類是代理者這一信息局部化的時候。

抽象工廠模式

意圖
抽象工廠模式(Abstract Factory)抽象工廠模式(Abstract Factory)
提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
適用性
  • 一個系統要獨立於它的產品的創建、組合和表示時。
  • 一個系統要由多個產品系列中的一個來配置時。
  • 當你要強調一系列相關的產品對象的設計以便進行聯合使用時。
  • 當你提供一個產品類庫,而只想顯示它們的接口而不是實現時。

建造者模式

意圖
將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
建造者模式建造者模式
適用性
  • 當創建複雜對象的算法應該獨立於該對象的組成部分以及它們的裝配方式時。
  • 當構造過程必須允許被構造的對象有不同的表示時。

原型模式

意圖
用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。
原型模式原型模式
適用性
  • 當要實例化的類是在運行時刻指定時,例如,通過動態裝載;或者
  • 為了避免創建一個與產品類層次平行的工廠類層次時;或者
  • 當一個類的實例只能有幾個不同狀態組合中的一種時。建立相應數目的原型並克隆它們可能比每次用合適的狀態手工實例化該類更方便一些。

單例模式

意圖
保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
單例模式單例模式
適用性
  • 當類只能有一個實例而且客戶可以從一個眾所周知的訪問點訪問它時。
  • 當這個唯一實例應該是通過子類化可擴展的,並且客戶應該無需更改代碼就能使用一個擴展的實例時。
代碼示例
/** * Java代碼懶漢式單例模式 * 大屎蛋教程網 */class Singleton1 {    private static Singleton1 singleton1;    private Singleton1() {    }    public static Singleton1 getInstance() {        if (null == singleton1) {            singleton1 = new Singleton1();        }        return singleton1;    }} 
/** * Java代碼 餓漢式單例模式 */class Singleton2 {    private static Singleton2 singleton2 = new Singleton2();    private Singleton2() {    }    public static Singleton2 getInstance() {        return singleton2;    }}

適配器模式

意圖
將一個類的接口轉換成另外一個客戶希望的接口。Adapter 模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。
適配器模式適配器模式
適用性
  • 你想使用一個已經存在的類,而它的接口不符合你的需求。
  • 你想創建一個可以復用的類,該類可以與其他不相關的類或不可預見的類(即那些接口可能不一定兼容的類)協同工作。
  • (僅適用於對象Adapter)你想使用一些已經存在的子類,但是不可能對每一個都進行子類化以匹配它們的接口。對象適配器可以適配它的父類接口。

橋接模式

意圖
將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
橋接模式橋接模式
適用性
  • 你不希望在抽象和它的實現部分之間有一個固定的綁定關係。例如這種情況可能是因為,在程式運行時刻實現部分應可以被選擇或者切換。
  • 類的抽象以及它的實現都應該可以通過生成子類的方法加以擴充。這時B r i d g e 模式使你可以對不同的抽象接口和實現部分進行組合,並分別對它們進行擴充。
  • 對一個抽象的實現部分的修改應對客戶不產生影響,即客戶的代碼不必重新編譯。
  • C++)你想對客戶完全隱藏抽象的實現部分。在C++中,類的表示在類接口中是可見的。
  • 有許多類要生成。這樣一種類層次結構說明你必須將一個對象分解成兩個部分。Rumbaugh稱這種類層次結構為“嵌套的普化”(nested generalizations )。
  • 你想在多個對象間共享實現(可能使用引用計數),但同時要求客戶並不知道這一點。一個簡單的例子便是Coplien的String類,在這個類中多個對象可以共享同一個字元串表示(StringRep)。

組合模式

意圖
將對象組合成樹形結構以表示“部分-整體”的層次結構。C o m p o s i t e 使得用戶對單個對象和組合對象的使用具有一致性。
組合模式組合模式
適用性
  • 你想表示對象的部分—整體層次結構。
  • 你希望用戶忽略組合對象與單個對象的不同,用戶將統一地使用組合結構中的所有對象。

裝飾模式

意圖
動態地給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類更為靈活。
裝飾模式裝飾模式
適用性
  • 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。
  • 處理那些可以撤消的職責。
  • 當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用於生成子類。

門面模式

意圖
為子系統中的一組接口提供一個一致的界面,Facade模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
門面模式門面模式
適用性
  • 當你要為一個複雜子系統提供一個簡單接口時。子系統往往因為不斷演化而變得越來越複雜。大多數模式使用時都會產生更多更小的類。這使得子系統更具可重用性,也更容易對子系統進行定製,但這也給那些不需要定製子系統的用戶帶來一些使用上的困難。Facade可以提供一個簡單的預設視圖,這一視圖對大多數用戶來說已經足夠,而那些需要更多的可定製性的用戶可以越過Facade層。
  • 客戶程式與抽象類的實現部分之間存在著很大的依賴性。引入Facade將這個子系統與客戶以及其他的子系統分離,可以提高子系統的獨立性和可移植性。
  • 當你需要構建一個層次結構的子系統時,使用門面模式定義子系統中每層的入口點。如果子系統之間是相互依賴的,你可以讓它們僅通過Facade進行通訊,從而簡化了它們之間的依賴關係。

享元模式

意圖
運用共享技術有效地支持大量細粒度的對象。
享元模式享元模式
適用性
  • 一個應用程式使用了大量的對象。
  • 完全由於使用大量的對象,造成很大的存儲開銷。
  • 對象的大多數狀態都可變為外部狀態。
  • 如果刪除對象的外部狀態,那么可以用相對較少的共享對象取代很多組對象。
  • 應用程式不依賴於對象標識。由於Flyweight對象可以被共享,對於概念上明顯有別的對象,標識測試將返回真值。

代理模式

意圖
為其他對象提供一種代理以控制對這個對象的訪問。
代理模式代理模式
適用性
在需要用比較通用和複雜的對象指針代替簡單的指針的時候,使用Proxy模式。下面是一 些可以使用Proxy模式常見情況:
  1. 遠程代理(Remote Proxy)為一個對象在不同的地址空間提供局部代表。
  2. 虛代理(Virtual Proxy)根據需要創建開銷很大的對象。
  3. 保護代理(Protection Proxy)控制對原始對象的訪問。保護代理用於對象應該有不同 的訪問許可權的時候。
  4. 智慧型指引(Smart Reference)取代了簡單的指針,它在訪問對象時執行一些附加操作。 它的典型用途包括:
  5. 對指向實際對象的引用計數,這樣當該對象沒有引用時,可以自動釋放它(也稱為SmartPointers)。
  6. 當第一次引用一個持久對象時,將它裝入記憶體。
  7. 在訪問一個實際對象前,檢查是否已經鎖定了它,以確保其他對象不能改變它。

職責鏈模式

意圖
使多個對象都有機會處理請求,從而避免請求的傳送者和接收者之間的耦合關係。將這些對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個對象處理它為止。
職責鏈模式職責鏈模式
適用性
  • 有多個的對象可以處理一個請求,哪個對象處理該請求運行時刻自動確定。
  • 你想在不明確指定接收者的情況下,向多個對象中的一個提交一個請求。
  • 可處理一個請求的對象集合應被動態指定。

命令模式

意圖
將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可取消的操作
命令模式命令模式
適用性
  • 像上面討論的MenuItem對象那樣,抽象出待執行的動作以參數化某對象。你可用過程語言中的回調(callback)函式表達這種參數化機制。所謂回調函式是指函式先在某處註冊,而它將在稍後某個需要的時候被調用。Command模式是回調機制的一個面向對象的替代品。
  • 在不同的時刻指定、排列和執行請求。一個Command對象可以有一個與初始請求無關的生存期。如果一個請求的接收者可用一種與地址空間無關的方式表達,那么就可將負責該請求的命令對象傳送給另一個不同的進程並在那兒實現該請求。
  • 支持取消操作。Command的Execute操作可在實施操作前將狀態存儲起來,在取消操作時這個狀態用來消除該操作的影響。Command接口必須添加一個Execute操作,該操作取消上一次Execute調用的效果。執行的命令被存儲在一個歷史列表中。可通過向後和向前遍歷這一列表並分別調用Unexecute和Execute來實現重數不限的“取消”和“重做”。
  • 支持修改日誌,這樣當系統崩潰時,這些修改可以被重做一遍。在Command接口中添加裝載操作和存儲操作,可以用來保持變動的一個一致的修改日誌。從崩潰中恢復的過程包括從磁碟中重新讀入記錄下來的命令並用Execute操作重新執行它們。
  • 用構建在原語操作上的高層操作構造一個系統。這樣一種結構在支持事務(Transaction)的信息系統中很常見。一個事務封裝了對數據的一組變動。Command模式提供了對事務進行建模的方法。Command有一個公共的接口,使得你可以用同一種方式調用所有的事務。同時使用該模式也易於添加新事務以擴展系統。

解析器模式

意圖
給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。
解析器模式解析器模式
適用性
  • 當有一個語言需要解釋執行, 並且你可將該語言中的句子表示為一個抽象語法樹時,可使用解釋器模式。而當存在以下情況時該模式效果最好:
  • 該文法簡單對於複雜的文法, 文法的類層次變得龐大而無法管理。此時語法分析程式生成器這樣的工具是更好的選擇。它們無需構建抽象語法樹即可解釋表達式, 這樣可以節省空間而且還可能節省時間。
  • 效率不是一個關鍵問題最高效的解釋器通常不是通過直接解釋語法分析樹實現的, 而是首先將它們轉換成另一種形式。例如,正則表達式通常被轉換成狀態機。但即使在這種情況下, 轉換器仍可用解釋器模式實現, 該模式仍是有用的。

疊代器模式

意圖
提供一種方法順序訪問一個聚合對象中各個元素, 而又不需暴露該對象的內部表示。
設計模式(設計模式概念)
適用性
  • 訪問一個聚合對象的內容而無需暴露它的內部表示。
  • 支持對聚合對象的多種遍歷。
  • 為遍歷不同的聚合結構提供一個統一的接口(即, 支持多態疊代)。

中介模式

意圖
用一個中介對象來封裝一系列的對象互動。中介者使各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。
中介模式中介模式
適用性
  • 一組對象以定義良好但是複雜的方式進行通信。產生的相互依賴關係結構混亂且難以理解。
  • 一個對象引用其他很多對象並且直接與這些對象通信,導致難以復用該對象。
  • 想定製一個分布在多個類中的行為,而又不想生成太多的子類。

備忘錄模式

意圖
在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到保存的狀態。
備忘錄模式備忘錄模式
適用性
  • 必須保存一個對象在某一個時刻的(部分)狀態, 這樣以後需要時它才能恢復到先前的狀態。
  • 如果一個用接口來讓其它對象直接得到這些狀態,將會暴露對象的實現細節並破壞對象的封裝性。

觀察者模式

意圖
定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時, 所有依賴於它的對象都得到通知並被自動更新。
觀察者模式觀察者模式
適用性
  • 當一個抽象模型有兩個方面, 其中一個方面依賴於另一方面。將這二者封裝在獨立的對象中以使它們可以各自獨立地改變和復用。
  • 當對一個對象的改變需要同時改變其它對象, 而不知道具體有多少對象有待改變。
  • 當一個對象必須通知其它對象,而它又不能假定其它對象是誰。換言之,你不希望這些對象是緊密耦合的。

狀態模式

意圖
允許一個對象在其內部狀態改變時改變它的行為。對象看起來似乎修改了它的類。
狀態模式狀態模式
適用性
  • 一個對象的行為取決於它的狀態, 並且它必須在運行時刻根據狀態改變它的行為。
  • 一個操作中含有龐大的多分支的條件語句,且這些分支依賴於該對象的狀態。這個狀態通常用一個或多個枚舉常量表示。通常, 有多個操作包含這一相同的條件結構。State模式將每一個條件分支放入一個獨立的類中。這使得你可以根據對象自身的情況將對象的狀態作為一個對象,這一對象可以不依賴於其他對象而獨立變化。

策略模式

意圖
定義一系列的算法,把它們一個個封裝起來, 並且使它們可相互替換。本模式使得算法可獨立於使用它的客戶而變化。
策略模式策略模式
適用性
  • 許多相關的類僅僅是行為有異。“策略”提供了一種用多個行為中的一個行為來配置一個類的方法。
  • 需要使用一個算法的不同變體。例如,你可能會定義一些反映不同的空間/時間權衡的算法。當這些變體實現為一個算法的類層次時,可以使用策略模式。
  • 算法使用客戶不應該知道的數據。可使用策略模式以避免暴露複雜的、與算法相關的數據結構。
  • 一個類定義了多種行為, 並且這些行為在這個類的操作中以多個條件語句的形式出現。將相關的條件分支移入它們各自的Strategy類中以代替這些條件語句。

模版模式

意圖
定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。Te m p l a t e M e t h o d 使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。
模板模式模板模式
適用性
  • 一次性實現一個算法的不變的部分,並將可變的行為留給子類來實現。
  • 各子類中公共的行為應被提取出來並集中到一個公共父類中以避免代碼重複。這是Opdyke和Johnson所描述過的“重分解以一般化”的一個很好的例子。首先識別現有代碼中的不同之處,並且將不同之處分離為新的操作。最後,用一個調用這些新的操作的模板方法來替換這些不同的代碼。
  • 控制子類擴展。模板方法只在特定點調用“hook”操作,這樣就只允許在這些點進行擴展。

訪問者模式

意圖
表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用於這些元素的新操作。
訪問者模式訪問者模式
適用性
  • 一個對象結構包含很多類對象,它們有不同的接口,而你想對這些對象實施一些依賴於其具體類的操作。
  • 需要對一個對象結構中的對象進行很多不同的並且不相關的操作,而你想避免讓這些操作“污染”這些對象的類。Visitor使得你可以將相關的操作集中起來定義在一個類中。當該對象結構被很多套用共享時,用Visitor模式讓每個套用僅包含需要用到的操作。
  • 定義對象結構的類很少改變,但經常需要在此結構上定義新的操作。改變對象結構類需要重定義對所有訪問者的接口,這可能需要很大的代價。如果對象結構類經常改變,那么可能還是在這些類中定義這些操作較好。

設計步驟

綜述

如何把設計模式的採用和日益臨近的最後期限、緊縮的預算和很多公司現有的有限團隊資源相結合?以下是成功制訂設計模式的步驟。

通信和培訓

許多機構擁有領先技術,可能正式通過了設計師論壇的論證或者非正式的公認專家。這些領先廠商將推廣設計模式採用中的開放通信,並將培訓開發具體設計模式的團隊。通信應當跨開發團隊和項目以便預先防止採用豎井和多種惟一的實現(謹記每個Developer/Project AntiPattern的實現)。培訓可以採用正式的internal lunch-and-learns、正式的internal class或者派一些員工參加外部培訓。這些培訓方式將促進正確的設計模式應用程式。如果僅有極少的觀眾能夠參加培訓,最佳的候選人是那些感覺適合在回來後能夠培訓其同事的人。

設計模式指導

設計模式可用於使項目受益,但是他們也可能因為誤用而對應用程式造成損害。應當鼓勵採用他們,但是對其的採用應當受到審閱和驗證。設計模式可以包含在設計和開發過程中。在任何一種情況中,設計模式的使用應當由審閱者確認和驗證。在審閱過程中還可能會遇到這樣的情況,額外的設計模式不適用於最初包括的地方。即使環境中沒有進行正式的審閱,這一步驟也可以通過同事審閱或者團隊討論來完成。這一步驟中的審閱者要么是主要團隊的成員,要么與他們建立開放通信。
指導採用對於broad exposure類別的設計模式非常關鍵。這些設計模式具有很多相關的風險,因為他們將創建依賴性。這些依賴性可能在一些對象類中,例如,只工作在更加廣泛的DAO設計模式實現範圍中的數據訪問對象(DAO)、或者跨應用程式邊界(如使用Value Object設計模式在應用程式和應用程式層之間傳輸數據)。這些設計模式也可以由項目中的其他人或者不同項目的人實現,而且實現應當重新使用,不同於創建另一種獨特的實現。
重用實現,不只是設計模式
只要在創建自己的設計模式實現中有一定的滿足,團隊和公司就可以在重用發生在代碼層時,而不是設計創意層時獲得更多益處。使企業獲益的最初設計模式是改進的實現。但是,真正的目標是重用實現。重用實現將導致:a)其他可重用的類(取決於公共實現);b)縮短開發時間和降低成本;c)縮短維護時間和降低成本;d)在應用程式之間和內部輕鬆集成。
這種重用對broad exposure設計模式非常重要(有時是基本的)。這些設計模式創建了外部依賴性(集成將從公共實現中受益)或者產生全部的自定義類庫(如果有公共基礎將可重用)。isolated use設計模式也可以從重用中獲益,但是如果他們是根據具體情況定製的,他們就非常難以重用。
有時您可能會問自己:“如果重用比較好,為什麼設計模式和可以重用的實現不可以一同套用呢?”在我們討論設計模式如何使更多讀者獲益的時候才會討論這個問題。如果可能,如果已經預定義了實現,那么達到廣泛適用性這個目標就會非常困難。然而,一旦設計模式被套用到特殊的問題域或者技術基礎設施中,那么就可以重用在該環境中產生的實現。

架構中的設計

這看起來像是一件可怕的任務,需要掌握設計模式如何套用在實際情況中,如何構建優質的實現,以及如何促進重用實現。完成該任務的方法之一就是在環境中引入應用程式架構。應用程式架構提供了應用程式需要的結構,從而使開發團隊可以關注應用程式的域邏輯。這包含了已實現的設計模式。除了重用設計模式概念或者單個實現之外,可以在多個項目和應用程式之間重用架構。這種共享的公共實現確保了兼容性,並為開發和維護多種不同的實現提供了一種低成本替代方案。兼容性提供了重新使用需要的技術基礎。沒有足夠的篇幅在這裡深入討論架構的其他重要品質,如運行時監測和管理、可配置應用程式邏輯和適應性行為等。您可以從Carnegie Mellon Software Engineering Institute 中學習到更多有關架構的知識。

設計模式與重構

因為設計模式與重構遵循相同的面向對象原則,所以常常出現通過代碼一步步小粒度的重構而達到與典型設計模式相同或者類似的情況。
雖然重構並非一定會得到與設計模式完全相同的抽象結果,但是重構是對設計模式設計步驟的一大補充。“Refactoring to Patterns”可以使得設計模式的得到更順暢,利用重構小粒度、規範的測試又可以進一步的降低模式套用的風險。

四人組

GoF(“四人組”,又稱Gang of Four,即Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四人)的《設計模式》,原名《Design Patterns: Elements of Reusable Object-Oriented Software》(1995年出版,出版社:Addison Wesly Longman.Inc),第一次將設計模式提升到理論高度,並將之規範化。該書提出了23種基本設計模式。時至今日,在可復用面向對象軟體的發展過程中,新的設計模式仍然不斷出現。
設計模式四人組設計模式四人組

相關圖書

《設計模式:可復用面向對象軟體的基礎》
作者:[美] Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides
出版社: 機械工業出版社
副標題:可復用面向對象軟體的基礎
譯者:李英軍、馬曉星、蔡敏劉建中
出版年:2000-9
頁數:254
定價:35.00元
裝幀:平裝
叢書:計算機科學叢書
ISBN:9787111075752
《軟體秘笈:設計模式那點事》
設計模式(設計模式概念)
作者:鄭阿奇
出版社:電子工業出版社
ISBN:9787121147821
出版時間:2011-11-01
叢書名:魅力·實踐·發現
版次:1
頁數:628
裝幀:平裝
所屬分類:圖書 > 計算機與網際網路 > 軟體工程及軟體方法學
附屬檔案:CD光碟
定價:¥87.00
內容簡介
本書在第1章軟體設計模式概述後,從第2章到第24章詮釋23個軟體設計模式。每一種都以一個生活故事開始,然後是模式定義、模式分析、模式實現、設計原則和使用場合。模式實現通過Eclipse中的Java工程展開,採用軟體編程詮釋設計模式故事中的情節和操作,非常有趣。在這個基礎上,總結該軟體設計模式的設計原則,最後提出使用場合。第25章對各種軟體設計模式進行系統總結,第26章是各種軟體設計模式綜合套用。
軟道語錄
設計模式
設計模式就是軟體設計中對於特定問題的習慣的,通用的解決模式。
《設計模式:基於C#的工程化實現及擴展》
作者:王翔
出版社:電子工業出版社
出版時間:2009-1-1
字數:850000
版次:1
頁數:652
開本:16開
印次:1
紙張:膠版紙
ISBN :9787121075070
包裝:平裝
所屬分類:圖書 > 計算機/網路 > 程式設計 > C/C++/C#/VC/VC++
定價:¥98.00
專家推薦
本書立意明確,除了告訴你問題的類型與解法,還提供了可以立即演繹的程式代碼,相信這本案頭的工具書可以提供你一個不錯的思維模式,幫你造就有彈性、能擴充、易維護的軟體實體。
胡百敬 微軟MVP,台灣恆逸資訊資深講師,“資料庫鐵人”
作者從GOF23種經典設計模式開始,帶你走進模式的失門,小到細粒度的基礎模式,大到粗粒度的架構模式,本書都做了詳盡的講解。如果您還在為了軟體需求的無盡變化而煩惱不斷,為了在軟體設計領域更上一層樓而苦苦思索,希望本書能夠帶給您一些啟發。
李會軍 微軟MVP,部落格園專家,IT168專欄作者
本書很有特色的地方,就是以工程角度來闡釋模式,相較純粹的模式之說,則更具普遍的下手角度,C#語言的高級特性結合設計模式的經典思想,兩者相得益彰。
王濤 微軟MVP,部落格園專家,《你必須知道的.NET》作者
內容簡介
本書基於C# 2.0的語法,試圖將GOF 23中的模式以一種可工程化的公共庫而非Example的方式呈現給讀者。內容包括以下7部分。
第1篇主要是概括性的介紹;第2篇創建型模式介紹通過將實例化職責委託他方對象的辦法,隔離客戶程式與具體類型實例化的依賴關係,保證客戶程式(或者外部系統)獲得期望具體類型實例的、同時不必發生直接的引用;第3篇結構型模式的重點在於如何通過靈活的體系組織不同的對象,並在此基礎上完成更為複雜的類型(或者類型系統),而參與組合的各類型之間始終保持儘量鬆散的結構關係;第4篇行為型模式關注於套用運行過程中算法的提供和通信關係的梳理;第5篇主要介紹小顆粒度基礎模式和套用案例;第6篇主要介紹套用全局的模式化的實現方法,包括現2009年已經被普遍套用的N層模式及某些關鍵性框架產品採用的“微核心”模式;第7篇主要是一些針對Web和Web Service領域的模式設計技術。
本書主要針對對C#語言和.NET Framework平台有一定了解或有一定套用經驗的用戶,尤其適於那些希望運用模式技術在設計和開發方面多應對些挑戰的用戶。
作者簡介
王翔,軟體架構師,主要從事.NET、XML、公鑰基礎設施的開發。專注於數據(尤其是XML信息)的生產、加工、交換、提煉等過程。2009年參與了一系列有關套用密碼技術和PKI環境保護信息系統數據安全的項目。
最喜歡數學,平常案頭總是擺一本數學練習題。閒暇時間喜歡寫作,通過發表多種技術文章與國內外同行交流各種數據套用經驗。
項目間隙經常到各海濱城市徒步旅行、野外露營、出海航行、極限運動,這幾年烹飪也漸漸成為個人主要愛好。

相關詞條

熱門詞條

聯絡我們