軟件設計原則——GRASP

     Craig Larman氏在《Applying UML and Patterns》一書中提出了GRASP設計模式的概念。做者稱其爲設計模式,其實,更好的理解應該爲設計原則。由於,與GoF等設計模式不一樣的是,GoF等設計模式是針對特定問題而提出的解決方法,而GRASP則是站在面向對象設計的角度,告訴咱們怎麼樣設計問題空間中的類與它們的行爲責任,以及明確類之間的相互關係等等。GRASP能夠說是GoF等設計模式的基礎。java

      GRASP是General Responsibility Assignment Software patterns(通用職責分配軟件模式)的簡稱,它的核心思想是「職責分配(Responsibility Assignment)」,用職責設計對象:"Designing Objects with Responsibilities"。它包含了9個基本模式:
1 專家模式(Expert)
解決方案:將職責分配給具備履行職責所須要的信息的類
通俗點就是:該幹嗎幹嗎去,別管別人的閒事或者個人職責就是搞這個,別的事無論。
舉個簡單的例子,若是有一個類是專門處理字符串相關的類,那麼這個類只能有字符串處理相關的方法,而不要將日期處理的方法加進來。也就是提升軟件高內聚一種原則。
2 建立者(Creator)
解決方案:將建立一個類A的實例的職責指派給類B的實例,若是下列條件知足的話:
B聚合了A對象
B包含了A對象
B紀錄了A對象的實例
B要常用A對象
當A的實例被建立時,B具備要傳遞給A的初始化數據(也就是說B是建立A的實例這項任務的信息專家)
B是A對象的建立者
若是以上條件中不止一條成立的話,那麼最好讓B彙集或包含A
通俗點就是:我要用你因此我來建立你,請不要讓別人建立你
這個模式是支持低耦合度原則的一個體現
3 高聚合度或高內聚(High Cohesion)
解決方案:分配一個職責的時候要保持類的高聚合度
聚合度或內聚度(cohesion)是一個類中的各個職責之間相關程度和集中程度的度量。一個具備高度相關職責的類而且這個類所能完成的工做量不是特別巨大,那麼他就是具備高聚合度。
4 低耦合度或低耦合(Low Coupling)
解決方案:在分配一個職責時要使保持低耦合度。
耦合度(coupling)是一個類與其它類關聯、知道其餘類的信息或者依賴其餘類的強弱程度的度量。一個具備低(弱)耦合度的類不依賴於太多的其餘類。
5 控制者(Controller)
解決方案:將處理系統事件消息的職責分派給表明下列事物的類:
表明整個「系統」的類(虛包控制者)
表明整個企業或組織的類(虛包控制者)
表明真實世界中參與職責(角色控制者)的主動對象類(例,一我的的角色)
表明一個用況中全部事件的人工處理者類,一般用「<用例名>處理者」的方式命名(用例控制者)
這是一個控制者角色職責分配的原則,就是哪些控制應該分派給哪一個角色。
6 多態
當相關的可選擇的方法或行爲隨着類型變化時,將行爲的職責-使用多態的操做-分配給那些行爲變化的類型
也就是說盡可能對抽象層編程,用多態的方法來判斷具體應該使用那個類,而不是用if instanceof 來判斷該類是什麼接來執行什麼。
7 純虛構
一個純虛構意味着虛構某些事物,而不是到了無可奈何咱們才這樣作。
例,咱們的Sale類的數據要存入數據庫,可是他必須和數據庫接口相鏈接,若是將接口鏈接放入Sale類中勢必增長該類的耦合度,因此咱們能夠虛構一個類來處理與數據庫接口鏈接的問題。這個類就是咱們虛構出來的一個事物。
8 中介者
將職責分配給一箇中間對象以便在其餘構件或服務之間仲裁,這樣這些構件或服務沒有被直接耦合。這個中間對象(intermediary)在其餘構件或服務間建立一箇中介者(Indirection)。這個中間對象也就事7)中的純虛構。
9 不要和陌生人講話
分配職責給一個客戶端的直接對象以使它與一個間接對象進行協做,這樣客戶端無需知道這個間接對象。
這個模式-也被叫作(Demeter)準則。
通俗點就是:只與你直接的朋友們通訊
不要跟「陌生人」說話

每一個軟件單位對其餘的單位都只有最少的知識,並且侷限於那些與本單位密切相關的軟件單位數據庫

其餘設計原則編程

「開-閉」原則(Open-Closed Principle,或者OCP)
一個軟件實體應當對擴展開放,對修改關閉。

意思就是在設計一個模塊的時候,應當使這個模塊在不被修改的前提下被擴展。換言之,應當能夠在不修改代碼的狀況下改變這個模塊的行爲。設計模式

里氏代換原則(Liskov Substitution Principle, 或者LSP)

這個就是儘可能用多態的方法編程,也就是GRASP模式中的多態。eclipse

依賴倒轉原則(Dependency Inversion Principle, 或者DIP)
依賴倒轉原則講的是:要依賴於抽象,不要依賴於具體

就是說咱們儘可能在抽象層進行控制編程,要針對接口編程,不要針對實現編程。spa

接口隔離原則(Interface Segregation Principle, 或者ISP)

使用多個專門的接口比使用單一的總接口要好。也就是,從一個客戶類的角度來說:一個類對另一個類的依賴性應當是創建在最小的接口上的。插件

組合/聚合複用原則(Composition/Aggregation Principle, 或者CARP)設計

又叫合成複用原則。原則就是在一個新的對象裏面使用一些已有的對象,使之成爲新對象的一部分:新的對象經過向這些對象的委派達到複用已有功能的目的。也就是,要儘可能使用類的合成複用,儘可能不要使用繼承orm

變與不變的分離
      更擴展一步,就是將不一樣變化的組件進行隔離.最簡單的例子就是javabean中的存取器。它隔離了不變的接口和變化的內部屬性。這方面體現最好的我的以爲就是eclipse,經過變化的插件,eclipse能夠用來實現任何功能。
另外一種角度:高內聚、低耦合(High Cohesion、Low Coupling) 在面向對象的程序設計時,小到一個類,大到一個功能模塊,若是他們之間的相依性很高就會對整個軟件的開發形成諸般障礙。例如:當你修改一個類或者某一個模 塊的時候,相應的你要改動其餘的與之相依賴的類和模塊,使得程序很難維護;代碼會變得很難理解,一個很單一的操做,就會涉及到不少程序之間相互調用;程序 更是難以複用,當你想複用一個類的時候,對應的與之想依賴的類或方法也會被陸陸續續的添加進來。
        這就是咱們爲何要遵循這一原則的緣由,而高內聚和低耦合每每是伴隨在一塊兒出現的。低耦合其實就是兩個類或模塊之間聯繫的緊密程度,高內聚就是類中方法和 方法之間的職責相關性。要想避免低內聚、高耦合,解決辦法就是既要下降由於一個類的變化而對另外一個類產生的影響,又要保持類或模塊是有重點的、可理解的、 可管理的而且支持低耦合的,也就是更加精確的給一個類或者模塊分配職責。
        高內聚和低耦合是軟件開發中最重要的原則,grasp的其餘模式也是以高內聚、低耦合原則爲中心的。
信息專家(Information Expert)
        如何實現高內聚,也就是如何給類分配職責?咱們要遵循的原則就是把職責分配給具備完成該職責信息的那個類。
建立者(Creator)
如何分配建立對象的職責呢?原則就是當下列條件知足時(越多越好),由B建立A:
1.B頻繁的使用A
2.B包含或聚合了A
         舉個簡單的例子,若是類A實現了B接口,類C、D是類A的一個屬性,那麼C、D應該由A來建立,A應該由B來建立。若是C、D由B來建立,那麼當C或者D改變的時候,B 和A也要跟着改變,大大加強了B和C、D的之間的耦合度,違背了低內聚的原則。通俗點說就是若是B使用的了A,那麼就應該由B來建立A,而不是由其餘的類來建立。
控制器(Controller)
        在UI層外,應該由哪一個類來處理系統操做呢?原則就是把系統事件的處理職責分配給控制器類,這個控制器類就至關於MVC中的C。這個控制器類一般是系統事件放生 的用例的控制類。
多態(Polymorphism)
        根據類型的不一樣而發生變化的行爲的定義職責,應該分配給誰?
舉個簡單的例子,坐車去廣州,坐車算是一個行爲,可是這個行爲是能夠變化的,好比坐飛機、坐汽車或者坐火車,那麼坐車這個行爲的定義應該分配給誰呢?
        原則是經過多態操做把基於類型的可變行爲的定義職責分配給發生該行爲的類。放到JAVA當中來實現就是定義一個坐車的接口,而後具體的坐飛機、坐汽車或者坐火 車的行爲分別定義一個類來實現該功能,而後讓這三個具體的類去實現坐車接口。
純虛構模式(Pure Fabrication)
        非問題領域的職責應該分配給誰?
        咱們在設計類的時候,一般都儘可能的保持和現實世界當中的對象一致,那麼咱們從現實世界的對象抽象出來的類就叫作問題領域裏的類,那麼當咱們保存這個對象的 時候要操做數據庫,操做數據庫就是一個非現實世界存在的業務對象,他就是非問題領域的職責。
        這種職責分配的原則就是將非問題領域的職責分配給人工生成的類。好比問題領域的類一般是放到PO裏面的,他不該該包括CRUD等操做。那麼CRUD這些操做應該放 到一我的工生成的也就是咱們在業務邏輯之外加的一個類。
間接性(Indirection)
        爲了不兩個或多個事物之間直接耦合,應該如何分配職責?
        設計原則是將職責分配給中介對象。例如類A和類B是多對多的關聯關係,當A改變的時候,B須要作相應的改變,當B改變的時候,A須要作相應的改變,這是違反低耦 合原則的,解決方法就是在A和B之間加入一個C類,類C的屬性只有A和B,用C來記錄A和B之間的關係,當A想使用B或者B使用A的時候,他們都經過C來調用對方。
防止變異(Protected Variation)
        如何設計對象、系統和子系統,使其內部的變化或者不穩定因素不會對其餘元素產生不良影響?

        預計識別不穩定的因素,在其外部建立穩定的接口。例如:坐汽車去廣州當中的坐汽車就是一個不穩定的因素,之後也許會坐飛機或者火車,那麼咱們就要把坐汽車 抽象出一個坐車的接口,當有一天想坐火車的時候直接加一個實現的類就能夠了。對象

GRASP的主要特徵:
- 對象職責分配的基本原則。
- 主要應用在分析和建模上。
GRASP的核心思想的理解: 本身幹本身的事(職責的分配) 本身幹本身的能幹的事(職責的分配) 本身只幹本身的事(職責的內聚)。
相關文章
相關標籤/搜索