設計模式

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

使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 設計模式於己、於他人、於系統都是多贏的,設計模式使代碼編制真正工程化。設計模式是軟件工程的基石,如同大廈的一塊塊磚石一樣使代碼編制真正工程化

只有精通了設計模式,纔敢說真正理解了軟件工程。可以說,設計模式是每一個架構師所必備的技能之一。作爲一個面向對象設計程序員,只有精通了設計模式,才能擺脫碼奴的命運,成爲一個真正的軟件工程師,才能完成自身價值的飛躍和設計思想的昇華!



1、設計模式和框架

  可複用面向對象軟件系統現在一般劃分爲兩大類:應用程序工具箱和框架(Framework),我們平時開發的具體軟件都是應用程序,Java的API屬於工具箱;而框架是構成一類特定軟件可複用設計的一組相互協作的類,EJB(EnterpriseJavaBeans)是Java應用於企業計算的框架。

  框架通常定義了應用體系的整體結構類和對象的關係等等設計參數,以便於具體應用實現者能集中精力於應用本身的特定細節。框架主要記錄軟件應用中共同的設計決策,框架強調設計複用,因此框架設計中必然要使用設計模式。  另外,設計模式有助於對框架結構的理解,成熟的框架通常使用了多種設計模式,如果你熟悉這些設計模式,毫無疑問,你將迅速掌握框架的結構,我們一般開發者如果突然接觸EJBJ2EE等框架,會覺得特別難學,難掌握,那麼轉而先掌握設計模式,無疑是給了你剖析EJB或J2EE系統的一把利器。



2、設計模式的原則

近年來,大家都開始注意設計模式。那麼,到底我們爲什麼要用設計模式呢?爲什麼要提倡設計模式呢?

根本原因是爲了擺脫編程低效率,提高代碼複用,增強代碼健壯穩定,增加可維護性。


那怎麼才能實現代碼複用呢?

從面向過程到面向對象,是軟件設計誕生以來的邁出的最偉大的一步,面向對象程序設計成功解決了面向過程軟件編程的低效率問題,並且徹底改變了人們的編程思維,爲軟件設計揭開了新的篇章。然而,要實現面向對象設計,徹底擺脫面向過程設計思維,並不僅僅是隻要使用了一門面向對象的編程語言就能夠達到的。使用面向對象設計,可以設計出優秀的軟件,同樣也可以設計出糟糕的軟件。只有遵循一些特定的原則,才能設計出複用性高靈活性好的軟件來。

在運用面向對象的思想進行軟件設計時,需要遵循的原則一共有 6 條:

  1. 單一職責原則(Single Responsibility Principle)
  2. 里氏替換原則(Liskov Substitution Principle)
  3. 依賴倒置原則(Dependence Inversion Principle)
  4. 接口隔離原則(Interface Segregation Principle)
  5. 迪米特法則(Law Of Demeter)
  6. 開閉原則(Open Close Principle)

        在軟件設計的過程中,只要我們儘量遵循以上六條設計原則,設計出來的軟件纔會是一個優秀的軟件,它必定足夠健壯、足夠穩定,並以極大的靈活性來迎接隨時而來的需求變更等因素。



3、設計模式的四要素

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

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

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

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

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



4、設計模式分類概覽

《設計模式》一書,第 1 次將設計模式提升到理論高度,並將之規範化。書中一共總結了23種基本的設計模式,《設計模式》下載

這23種設計模式,幾乎涵蓋了面向對象設計過程中所有問題的解決方案,書中提到的23種設計模式分別是:

設計模式

(Design Pattern)

創建型

(Creational)

結構型

(Structural)

行爲型

(Behavioral)

1、Abstract Factory(抽象工廠)

2、Builder(建造者)

3、Factory Method(工廠方法)

4、Prototype(原型)

5、Singleton(單態)

 

 

 

 

 

 

 

6、Adapter(適配器)

7、Bridge(橋模式)

8、Composite(組合)

9、Decorator(裝飾)

10、Façade(外觀)

11、Flyweight(享元)

12、Proxy(代理)

13、Chain of Responsibility(職責鏈)

14、Command(命令)

15、Interpreter(解釋器)

16、Iterator(迭代器)

17、Mediator(中介)

18、Memento(備忘錄)

19、Observer(觀察者)

20、State(狀態)

21、Strategy(策略)

22、Template Method(模板方法)

23、Visitor(訪問者)



5、設計模式的設計場景

那麼如此多的設計模式又是從何而來呢?

《易經》有云:“易有太極,是生兩儀,兩儀生四象,四象生八卦”,意思就是說世界萬物皆有起源。

設計模式的起源,是面向對象程序設計思想,是面向對象設計的精髓——抽象。面向對象通過類和對象來實現抽象,實現時產生了面向對象的三個重要機制:封裝、繼承、多態,正是這三個機制衍生出了各種各樣的設計模式。

設計模式的支持設計

目的

設計模式

可變方面

創建

(Creational)

1、Abstract Factory

2、Builder

3、Factory Method

4、Prototype

5、Singleton

產品對象家族

如何創建一個組合對象

被實例化的子類

被實例化的類

一個類的唯一實例

結構

(Structural)

6、Adapter

7、Bridge

8、Composite

9、Decorator

10、Façade

11、Flyweight

12、Proxy

對象的接口

對象的實現

一個對象的結構和組成

對象的職責,不生成子類

一個子系統的接口

對象的存儲開銷

如何訪問一個對象,該對象的位置

行爲

(Behavioral)

13、Chain of Responsibility

14、Command

15、Interpreter

16、Iterator

17、Mediator

18、Memento

19、Observer

20、State

21、Strategy

22、Template Method

23、Visitor

滿足一個請求的對象

何時、怎樣滿足一個請求

一個語言的文法和解釋

如何遍歷、訪問一個聚合的各元素

對象間如何交互、與誰交互

一個對象中哪些私有信息存放在該對象之外,以及在什麼時候進行存儲

多個對象依賴於另外一個對象,而這些對象又如何保持一致

對象的狀態

算法設計

算法中的某些步驟

某些可作用於一個(組)對象上的操作,但不修改這些對象的類



6、設計模式的分類描述

設計模式分爲創建型模式、結構型模式、行爲型模式

設計模式的分類描述

創建型模式

1.抽象工廠模式

爲一個產品族提供了統一的創建接口。當需要這個產品族的某一系列的時候,可以從抽象工廠中選出相應的系列創建一個具體的工廠類。

2.建造者模式

將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。

3.工廠方法模式

定義一個接口用於創建對象,但是讓子類決定初始化哪個類。工廠方法把一個類的初始化下放到子類。

4.原型模式

用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。

5.單例模式

確保一個類只有一個實例,並提供對該實例的全局訪問。

5.多例模式

確保一個類只有命名的實例,並提供對這些實例的全局訪問。

對象池模式

通過回收利用對象避免獲取和釋放資源所需的昂貴成本。

惰性初始模式

推遲對象的創建、數據的計算等需要耗費較多資源的操作,只有在第一次訪問的時候才執行。

資源獲取爲初始化

通過綁定到合適對象的生命週期來確保資源被適當地釋放。

結構型模式

6.適配器模式

將某個類的接口轉換成客戶端期望的另一個接口表示。適配器模式可以消除由於接口不匹配所造成的類兼容性問題。

7.橋接模式

將一個抽象與實現解耦,以便兩者可以獨立的變化。

8.組合模式

把多個對象組成樹狀結構來表示局部與整體,這樣用戶可以一樣的對待單個對象和對象的組合。

9.裝飾模式

向某個對象動態地添加更多的功能。修飾模式是除類繼承外另一種擴展功能的方法。

10.外觀模式

爲子系統中的一組接口提供一個一致的界面, 外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。

11.享元

通過共享以便有效的支持大量小顆粒對象。

12.代理

爲其他對象提供一個代理以控制對這個對象的訪問。

行爲型模式

13.職責鏈

爲解除請求的發送者和接收者之間耦合,而使多個對象都有機會處理這個請求。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它。

14.命令

將一個請求封裝爲一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可取消的操作。

15.解釋器

給定一個語言, 定義它的文法的一種表示,並定義一個解釋器, 該解釋器使用該表示來解釋語言中的句子。

16.迭代器

提供一種方法順序訪問一個聚合對象中各個元素, 而又不需暴露該對象的內部表示。

17.中介者

包裝了一系列對象相互作用的方式,使得這些對象不必相互明顯作用,從而使它們可以鬆散偶合。當某些對象之間的作用發生改變時,不會立即影響其他的一些對象之間的作用,保證這些作用可以彼此獨立的變化。

18.備忘錄

備忘錄對象是一個用來存儲另外一個對象內部狀態的快照的對象。備忘錄模式的用意是在不破壞封裝的條件下,將一個對象的狀態捉住,並外部化,存儲起來,從而可以在將來合適的時候把這個對象還原到存儲起來的狀態。

19.觀察者模式

在對象間定義一個一對多的聯繫性,由此當一個對象改變了狀態,所有其他相關的對象會被通知並且自動刷新。

20.狀態

讓一個對象在其內部狀態改變的時候,其行爲也隨之改變。狀態模式需要對每一個系統可能取得的狀態創立一個狀態類的子類。當系統的狀態變化時,系統便改變所選的子類。

21.策略

定義一個算法的系列,將其各個分裝,並且使他們有交互性。策略模式使得算法在用戶使用的時候能獨立的改變。

22.模板方法

模板方法模式準備一個抽象類,將部分邏輯以具體方法及具體構造子類的形式實現,然後聲明一些抽象方法來迫使子類實現剩餘的邏輯。不同的子類可以以不同的方式實現這些抽象方法,從而對剩餘的邏輯有不同的實現。先構建一個頂級邏輯框架,而將邏輯的細節留給具體的子類去實現。

23.訪問者

封裝一些施加於某種數據結構元素之上的操作。一旦這些操作需要修改,接受這個操作的數據結構可以保持不變。訪問者模式適用於數據結構相對未定的系統,它把數據結構和作用於結構上的操作之間的耦合解脫開,使得操作集合可以相對自由的演化。

空對象

通過提供默認對象來避免空引用。

黑板

廣義的觀察者在系統範圍內交流信息,允許多位讀者和寫者。

規格

以布爾形式表示的可重綁定的商業邏輯。

在面向對象軟件設計的發展過程中,除了《設計模式》一書中提到的23中設計模式之外,新的設計模式仍然不斷出現。


若想更進一步瞭解關於面向對象設計的背景,參考接口模式內聚耦合

若想更進一步瞭解關於面向對象編程的背景,參考繼承重載多態接口


MVC(Model-View-Controller,模型-視圖-控制器)是軟件工程中的一種軟件架構模式,它把軟件系統分爲三個基本部分:模型(Model)、視圖(View)、控制器(Controller)。

MVC不是一種設計模式(Design Pattern),而是一種架構模式(Architectural Pattern),用以描述應用程序的結構以及結構中各部分的職責和交互方式。它最先是在1979年的時候第一次被人提出,不過,當時環境有些不同,網絡應用的概念在當時還不存在。

提姆·伯納斯李(Tim Berners-Lee)在上世紀九十年代初期的時候播種下了萬維網(WWW)的種子,並永遠的改變了世界。目前我們在網絡開發中所採用的這種模式實際上是原版模式的一個改編版。這種架構模式的瘋狂流行是由於兩個極其流行的開發框架將這種模式包含了進來,它們是:StrutsRuby on Rails。這兩個開發框架給稍後誕生的數百框架打上了深深的烙印。


1、 MVC 三層架構

模型(Model): 數據模型用於封裝與應用程序的業務邏輯相關的數據以及對數據的處理方法。模型有對數據直接訪問的權力,例如對數據庫的訪問。“模型”不依賴“視圖”和“控制器”,也就是說,模型不關心它會被如何顯示或是如何被操作。但是模型中數據的變化一般會通過一種刷新機制被公佈。爲了實現這種機制,那些用於監視此模型的視圖必須事先在此模型上註冊,從而,視圖可以瞭解在數據模型上發生的改變。(比較:軟件設計模式中的觀察者模式)

視圖(View): 視圖層能夠實現數據有目的的顯示(理論上,這不是必需的)。在視圖中一般沒有程序上的邏輯。爲了實現視圖上的刷新功能,視圖需要訪問它監視的數據模型,因此應該事先在被它監視的數據那裏註冊。

控制器(Controller): 控制器起到不同層面間的組織作用,用於控制應用程序的流程。它處理事件並作出響應。“事件”包括用戶的行爲和數據模型上的改變。


  • 控制器Controller)- 負責轉發請求,對請求進行處理。
  • 視圖View)   - 界面設計人員進行圖形界面設計。
  • 模型Model) - 程序員編寫程序應有的功能(實現算法等)、數據庫專家進行數據管理和數據庫設計(可以實現具體的功能)。


2、MVC原理

MVC(模型-視圖-控制器)架構模式背後的思想非常簡單,我們的應用程序中必須區分下面這些職責:



應用程序被分成了三個主要的部分,每個部分負責掌管不同的任務。



3、MVC模式的網絡應用

控制器(Controller)

控制器掌管着用戶的請求(當用戶點擊圖形用戶界面(GUI)上的元素執行操作時,控制器會收到HTTP GET或者POST請求)。它的主要功能就是調用並協調需要的資源/對象來執行用戶請求。通常控制器會爲任務調用合適的模型,以及選擇合適的視圖。

模型(Model)

模型是指運用於數據之上的數據規則和數據內容,它一般對應於應用程序所要管理的對象。在軟件系統中,任何事物都可以被抽象成可以對其以某種方式進行處理的數據模型。應用程序中的用戶,信息以及圖書是什麼?它們只是一堆必須按照對應規則處理的數據(日期不能是未來的日期,電子郵件有特定的格式,名字的長度不能超過多少字符等等)。


模型給控制器提供了一個用戶請求內容對應的數據表達(比如信息,書,相冊)。不管我們如何向用戶展示,這個數據模型都不會變。這也是我們爲什麼可以隨意選擇使用哪個視圖來展示數據的原因。模型包含我們應用程序邏輯中最重要的組成部分,這些邏輯運用於我們要處理的問題過程中。控制器更多的是包含應用程序自身的內部組織邏輯。


視圖(View)

視圖提供了展示模型數據的不同方式。它可能是數據填充的模板。視圖可以有多個,而控制器則決定使用哪個視圖。一個網絡應用通常由許多控制器,模型和視圖組成。控制器可以被看成是一個主控制器,用於接收用戶的所有請求,然後在調用特定的控制器來處理不同的情況。



4、MVC 優點

MVC的一個最明顯好處就是它將視圖展示和應用邏輯清晰的分離開來。

對不同用戶以及不同設備類型的支持一直是當下的一個常見問題,例如:

來自臺式電腦和手機的請求所得到的視圖應該是不相同的,模型會返回完全相同的數據,但是不同的地方是控制器會選擇使用的視圖文件來展示數據(我們可以把它看作是不同的模板)。

除了將視圖從業務邏輯中分離開外,MVC的分離也降低了大型應用設計的難度,代碼也更具結構性,因此也更容易維護,測試和重用。



5、MVC 適用場景

MVC模式的缺點是由於它沒有明確的定義,所以完全理解MVC模式並不是很容易。使用MVC模式需要精心的計劃,由於它的內部原理比較複雜,所以需要花費一些時間去思考。開發一個MVC模式架構的工程,將不得不花費相當可觀的時間去考慮如何將MVC模式運用到應用程序中,同時由於模型和視圖要嚴格的分離,這樣也給調試應用程序帶來了一定的困難。每個構件在使用之前都需要經過徹底的測試。另外由於MVC模式將一個應用程序分成了三個部件,所以這意味着同一個工程將包含比以前更多的文件。
過去MVC模式並不適合小型甚至中等規模的應用程序,這樣會帶來額外的工作量,增加應用的複雜性。但現在多數軟體設計框架,能直接快速提供MVC骨架,供中小型應用程序開發,此問題不再存在。對於開發存在大量用戶界面,並且邏輯複雜的大型應用程序,MVC將會使軟件在健壯性、代碼重用和結構方面上一個新的臺階。儘管在最初構建MVC模式框架時會花費一定的工作量,但從長遠的角度來看,它會大大提高後期軟件開發的效率。



6、 MVC 實現示例

1)MFC

MFC(Microsoft Foundation Classes) Document/View架構,是微軟早期對於MVC模式的實現,MFC將工程分成CView 和 CDocument 兩大類,其中的Document對應MVC中的Model,View相當於MVC中的View+Controller,再加上CWinApp類別,合成三大項,但是MFC基本上是一個失敗的MVC模式作品。
由於MFC之下的Document/View定義過於模糊,未將Controller(MessageMap)部份取出,因此Controller可以置入View或Document,但不管置入哪一方面,都會與View或Document綁死,沒有彈性。


2)Swing

Swing,是一個標準的MVC結構。ComponentUI代表View,負責描畫組件。組件尤其Model層,比如JTextField的Document, JTable的TableModel, JTree的TreeModel等等。

而Control可能不是很明顯,我們或許可以簡單的將其Event機制看作一個Swing團隊開發給開發者的Controller。

作爲Java開發者, 如果想理解MVC的結構,學習Swing的確是個不錯的選擇。


3).NET(ASP.NET、VB.NET、C#.NET

ASP.NET,針對視圖(View)和控制器(Controller)的模式沒有被很好地定義,而模型(Model)則留給開發者去設計。

ASP.NET 不嚴格需要一個模型,開發者可以自行選擇創建一個模型類,但是很多人選擇放棄這一步,直接把事件處理放在控制器裏處理任何計算、數據保存等等。但用模型來包含商業邏輯和數據存取是可實現的。


4)Qt Design

Qt,是一個跨平臺的C++應用程式開發框架,廣泛用於開發GUI程式,這種情況下又被稱爲部件工具箱,也可用於開發非GUI程式,比如控制檯工具和服務器。

Qt Design 開發界面類似於ASP.NET,把視圖(View)和控制器(Controller)隔離看來,模型(Model)由設計者自己設計。


經過多年發展,Qt不但擁有了完善的C++圖形庫,而且近年來的版本逐漸整合了數據庫、OpenGL庫、多媒體庫、網絡、腳本庫、XML庫、WebKit庫等等,其核心庫也加入了進程間通信、多線程等模塊,極大的豐富了Qt開發大規模複雜跨平臺應用程序的能力,真正意義上實現了其研發宗旨“Code Less; Create More; Deploy Anywhere.”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章