1. 程式人生 > >面向物件開發與面向物件設計模式的幾個核心的思想和概念 -java

面向物件開發與面向物件設計模式的幾個核心的思想和概念 -java

  面向物件方法,OO方法所具有的模組化、資訊封裝與隱蔽、抽象性、繼承性、多樣性等獨特之處,這些優異特性為研製大型軟體、提高軟體可靠性、可重用性、可擴充性和可維護性提供了有效的手段和途徑。Java主要特徵:封裝性,繼承性,多型性.

>>>> 面向物件開發的幾個核心思想

1、問題領域、物件、屬性、狀態、行為、方法、實現

問題領域:
  指軟體系統所模擬的真實世界中的系統,在現實生活中,比較常見的比如,稅收、社保、銀行、商場等等,都可以使用軟體來進行模擬,這些就是軟體所針對的問題領域。

物件:物件是對問題領域中的事物的一種抽象。
1)所有的東西都是物件,萬物皆物件,問題領域中的實體和概念都可以抽象為物件。
2)世界上沒有完全相同的兩片葉子,每個物件都是唯一的,物件的唯一性來自於真實世界中的事物的唯一性,即使在系統中java的兩個物件,記憶體地址也未必相同。
3)每個物件具有屬性和行為。
4)每一個物件都具有狀態,狀態的意思就是在某一個時間點上,物件的各個屬性的取值情況。
5)物件都屬於一個類,每個物件都是某一個類的例項,類是具有相同屬性和行為的物件的集合,同一個類的所有的例項都具有相同的屬性,表示他們的屬性的含義是相同的,但是他們的狀態未必是相同的,也就是屬性的取值未必是一樣的。

2、類、型別


類:
 類是一組具有相同屬性和行為的物件的抽象。類以及類的關係構成了物件模型的主要內容。
 面向物件變成的主要任務就是定義物件模型中的各個類。
 物件是類的例項,類是物件的模板。

3、訊息、服務
訊息可以理解為引數,服務,就是方法返回的值。

4、介面
什麼是介面?
  物件,通過介面對提供服務。在現實的世界中,介面是實體,但是在面向物件的範疇中,介面是一個抽象的概念,指的是系統對外提供的服務。系統的介面描述系統能夠提供哪些服務,但是不包含服務的實現的細節。物件是最小的子系統,每個物件都是服務提供者,因此每一個物件都具有介面。
  站在使用者的角度上,物件中所有向使用者公開方法的宣告構成了物件的介面。使用者呼叫物件的公開方法來獲得服務,使用者在獲得服務的時候,不需要關心物件到底是如何實現服務的。
  介面,是實現系統之間鬆耦合的有力手段。
  計算機系統也是一個充分利用介面來提高系統鬆耦合的例子,介面還提高了系統的可擴充套件性。

在java語言中,介面有兩個方面的意思:
  1)介面是指概念性的介面,也就是系統對外提供的所有的服務,在物件中表現的是public型別的方法的宣告。
  2)是指interface為關鍵字定義的實實在在的介面,也成為介面型別,用於明確的描述系統所提供的服務,能夠更加清晰的把系統的實現細節與介面分離。

5、封裝、透明

封裝
  封裝是指隱藏物件的屬性和實現的細節,僅僅對外公開介面,封裝能夠帶來的優點如下:
1)便於使用者能夠正確、方便的理解和使用系統,防止使用者錯誤修改系統的屬性。
2)有助於建立各個系統之間的鬆耦合關係,提高系統的獨立性,當一個系統的實現發生變化的時候,只要她的介面不發生變化,就不會影響到其他的系統。
3)提高系統的可重用性,每個系統都是一個相對獨立的整體,可以在多種環境中得到重用。
4)降低了構建大型系統的風險,就類似於搭積木一樣,個別的系統不成功,但是程式碼還是可以被重用的。

一個設計良好的系統會封裝所有的實現細節,把它的介面與實現能夠清晰的隔離起來,系統之間只通過介面進行通訊。面向物件的程式語言主要通過訪問控制機制來進行封裝,   這種機制能夠控制物件的屬性和方法的可訪問性。在java語言中提供瞭如下四種方式的訪問級別:
  public(公開)private(私有)protected(同一個包、子類)default(同一個包)
  把儘可能多的東西藏起來,然後對外提供間接的介面,如果封裝的程度越高,那麼相對的獨立性就越高,這樣使用起來就會更加的方便。
  把所有的屬性封裝起來,至少有幾個好處:更符合客觀世界規律、更靈活的控制屬性訪問級別、防止使用者錯誤操作、有助於物件封裝實現細節。

6、抽象

抽象:
  從特定的角度出發,從已經存在的一些事物當中抽取我們所關注的細節,形成一個新的事物的思維過程。抽象是一種從具體到抽象、由複雜到簡單的思維方式。
  三種類型的抽象:
1)從問題領域到軟體模型中的物件的抽象
2)從物件到類的抽象
3)從子類到父類的抽象

在java語言中,抽象有兩種意思:
1)抽象,是一種思維過程,包含上面三種方式的抽象
2)抽象,是一個形容詞,可以用來修飾類以及方法,如果一個方法被abstract修飾的話,則說明這個方法沒有被具體實現,如果一個類被abstract修飾,則說明這個是抽象類,不能被例項化。

7、繼承、擴充套件、覆蓋
  在父類和子類之間同時存在著繼承和擴充套件的關係。子類繼承父類的屬性以及方法,同時子類中還可以擴展出新的屬性以及方法,並且還可以覆蓋父類當中方法的實現方式。
  繼承與擴充套件同時提高了系統的可重用性和可擴充套件性。公有繼承 私有繼承 保護繼承
  繼承與擴充套件導致了面向物件軟體開發領域中的架構類軟體系統的發展。

如何在一些通用的軟體架構的基礎上進行擴充套件呢?
  這些通用的軟體架構中都提供了一些擴充套件點,簡單的說,這些擴充套件點就是為了讓使用者進行繼承和擴充套件的類。這些類已經具備了一些功能,並且能夠和軟體中的其他的類能夠進行緊密的協作,使用者只需要建立這些類的子類,然後在這些子類中增加新的功能或者是重新實現某些功能,使用者定義的子類能夠和系統中原有的類進行和諧融洽的協作。
  比如:J2EE、Servlet、JSP、EJB、Struts、JSF、Spring這些都是一些通用的架構。

8、組合
   組合 是一種用多個子系統來組裝出複雜系統的有效的手段。
  對於一個組合系統,組合系統和他的子系統是聚集關係,子系統之間則是關聯關係或者是依賴關係(在UML中的定義)

面向物件的範疇中,組合具有以下的特點:
 1)在軟體的分析和設計的階段,簡化為複雜系統建立物件的模型。在建立物件模型的時候,通常首先識別問題領域的粗粒度物件,然後對該物件進行分解,比較符合人類的思維。
 2)在軟體程式設計的階段中,假話建立複雜系統的過程,只需要分別建立獨立的子系統,然後將其組合起來,就構成了一個複雜的系統。而且允許第三方參與系統的建設,提高了構架複雜系統的效率。
 3)向使用者隱藏系統的複雜度。
 4)提高程式程式碼的可重用性,一個獨立的子系統可以被組合到多個複雜的系統當中。

9、多型、動態繫結
  多型,是指系統A訪問系統B提供的服務的時候,系統B可以通過多種方式來提供服務,而這一切對於系統A是透明的。
  動態繫結,一個介面=new 實現類,這個實現類在執行的時候並不知道,可能是實現類A,也可能是實現類B,java虛擬機器的這種執行機制被稱為動態繫結。
  抽象機制和動態繫結機制能夠提高系統之間的鬆耦合性。

需要注意的一點是:抽象機制是開發人員在開發過程當中使用的機制,但是動態繫結機制是在java虛擬機器執行的過程中提供的機制。

>>>> 面向物件設計模式的幾個核心思想: 高聚合低耦合

  面向物件,將世界歸納為一句話:萬事萬物皆物件。
  在沒有面向物件之前,軟體的可維護性是相當的爛,主要原因有四個:過於僵硬;過於脆弱;複用率低;黏度過高
  在軟體設計過程當中無論那種設計思維都把可拓展性、靈活性、可插入性作為軟體設計的一個基本的指導思想。

  設計模式的研究當中一個非常重要的概念就是:複用,那麼什麼是複用呢?軟體的複用又有那些好處呢?複用又有那些基本的形式呢?複用和可拓展性、靈活性、可插入性又有那些關聯或者關係呢?
  首先,複用就是重複使用的意思。軟體複用帶來了幾個比較明顯的好處:1,較高的生產率,2.較高的軟體質量,3.恰當的使用複用可以改善軟體的系統的可維護性。
  一個可複用的軟體可以為將來的軟體開發節省開發使用的時間和費用,一個越頻繁使用的構件那麼以後開發投資就相對越少。如果一個軟體的複用路越高,那麼發現它存在的缺陷就更快,從而也可以更為徹底的排除這種缺陷,這樣很明顯有利於系統的維護。更為重要的一點是,複用與系統的可維護行有著直接的關係。
  軟體複用包括:程式碼的複製與貼上;演算法的複用;資料結構的複用,模型複用。

    在面向物件的語言當中資料的抽象化和繼承的關係使得概念和定義可以複用;多型性使得實現和應用可以複用。而抽象化和封裝可以保證和促進系統的可維護性。面向物件的複用的焦點不是函式不是演算法等細節,而是體現在巨集觀意義上的商業邏輯的抽象的層次上,而這些是提高複用性和保證提高可維護性的關鍵所在。
    在面向物件的設計當中,抽象的層次應該是相對穩定的部分,也是複用的焦點,抽象模組相對於具體的模組獨立,從而具體模組的內部結構的變化就不會影響到抽象層次的結構,因而抽象層次的模型複用就會較為容易。

  在面向物件的領域裡邊,可維護性複用是以設計原則和設計模式為基礎的。
系統的可拓展性由:開閉原則,里氏代換原則,依賴倒轉原則和組合/聚合複用原則所保證。
系統的靈活性由:  開閉原則、迪米特法則、介面隔離原則所保證
系統的可插入性由:開閉原則、里氏代換原則,組合/聚合複用原則以及依賴倒轉原則所保證。

>>> 1.開閉原則
  開閉原則的核心我們總結為:對拓展開放,對修改關閉。說的直白點就是:在模組不被修改的的前提下可以被拓展。
 優點:
  通過拓展,可以提供新的行為,以滿足新的需求,使其具有一定的靈活性和適應性。
  對已有模組,特別是最為重要的抽象模組不能再被修改,使得變化中的軟體有一定的穩定性和延續性。
  在開閉原則當中最為關鍵的就是:抽象化。從另外一個角度講就是所謂的“對可變性的封裝原則”。這樣就意味著有兩點:
  1、可變性不應該散落到程式碼的角落,而應該白封裝到物件裡。繼承不應當被看作是封裝變化的方法,而應該被認為是從一般的物件生成特殊物件的方法。
  2、一種可變性,不應當與另一種可變性混合(設計模式的類圖和繼承結構一般都不會超過兩層)。

>>> 2.里氏代換原則是繼承和複用的一個基石。
  里氏代換原則:任何基類可以出現的地方,子類一定可以出現。
  這個是對開閉原則的一個補充。開閉原則的關鍵是抽象化,里氏代換原則則是對實現抽象化具體步驟的規範化。

>>> 3.依賴倒轉原則
  核心是:依賴於抽象,而不依賴於具體的實現。開閉原則是目標,依賴倒轉原則是一種手段。違反了依賴倒轉原則就不可能達到開閉原則的要求。

>>> 4.合成/聚合複用原則
  核心:儘量合成/聚合,而不是使用繼承關係達到複用的目的。合成/聚合複用原則和里氏代換原則相輔相成,前者要求設計師首先考慮合成和聚合關係,後者則要求在使用繼承關係的時候,必須確定這個關係符合這一條件。

  依賴也叫耦合,耦合分為三種,零耦合(如果兩個類沒有耦合關係),具體耦合(發生在兩個具體的或者說是可以例項化的類之間,經由一個類對另一個具體類的直接引用造成的),抽象耦合(發生在一個具體的類和一個抽象類或者介面之間的,使兩個必須發生關係的類之間存在最大的靈活性)。

抽象不應當依賴與細節,而細節應當依賴於抽象。也就是針對介面程式設計,而不要針對實現程式設計。以抽象的方式耦合是依賴倒轉原則的關鍵。里氏代換原則是依賴倒轉原則的一個基礎。
 
  組合/聚合複用原則
    核心:要儘量使用合成聚合,儘量不要使用繼承。
    聚合用來表示“擁有”關係或者整體與部分的關係。而合成是一種表示強的多的“擁有”關係。上以篇博文中有提及這兩者的區別。

>>> 5.迪米特法則
    核心:一個軟體的實體應當儘可能的減少和其他實體發生相互作用。
    迪米特法則所談論的就是對物件之間的資訊量、流線以及資訊的影響的控制。在軟體系統當中,一個模組設計的好不好的最主要也是最重要的標識就是該模組在多大程度上將自己的內部資料和其他有關的細節隱蔽起來。

  在類的劃分上應當建立有弱耦合的類;
  在類的設計結構上,每一個類都應當儘量降低成員的訪問許可權,一個類不應當public自己的屬性而應該提供取值和賦值的方法。 
在類的設計上,只要有可能就應當設定成不變類。
在對其他類的引用上,一個物件對其他物件的引用應當降到最低。


>>> 6.介面隔離原則
  核心:客戶端應該儘可能小的單獨的介面,而不要提供大的總的介面。
  介面隔離原則和廣義的迪米特法則都是對一個軟體的實體與其他的軟體實體的通訊的限制。廣義的迪米特法要求儘可能的減少通訊的寬度和深度,介面隔離原則限制的是通訊的寬度。遵循這兩個法則會使一個系統軟體,在功能拓展的過程當中,不會將修改的壓力傳遞到其他物件。

    以上就是設計模式當中應該注意的幾個原則,也是指導設計的一個關鍵性的原則。在設計軟體的時候,應該充分的考慮這幾個基本原則,同時也要考慮到軟體或者其他工具本身,以及軟體經濟成本和時間成本等因素的一些制約,所以需要綜合來考慮分析,用最合適的方式來開發和維護軟體,避免成本虛高,設計過度的情形出現,總之,在允許的條件情況下用最合的的設計模式進行軟體開發是最值得推薦的。