1. 程式人生 > >JAVA設計模式---1-5

JAVA設計模式---1-5

設計模式的用處:

先假設一個需求:使用java語言設計一個計算器程式,要求接收控制檯輸入的兩個數字和一個運算子號(+ - * /)中的一個。你會怎麼設計?

是不是也是開始一個main方法,然後“請輸入第一個數字” ---“請輸入第二個數字” --請輸入運算子

--判斷輸入的運算子,然後根據運算子輸出結果的形式呢?

程式沒有任何問題,但是程式存在的最大問題複用性問題,如果修改需求是否需要修改原始碼呢?如果讓你用面向物件的思想去做呢?或許你會定義一個運算子Operator類,裡面定義一個方法getResult(),將兩個數字和運算子都傳進去,直接獲取結果。這樣完美的解決了複用的問題,也體現了面向物件的思想,但是如果有一天我想加一個開根計算呢?是否又需要修改原始碼了呢?或者重新定義一個? 我們可以想想java的三大特性,封裝、繼承、多型。我們上面的解決思路只是用了一個封裝的特性,剩下兩個沒有用到,那麼如何通過繼承和多型完成該程式的複用性和解耦合呢?如何避免在變需求的時候恨不得跳樓似的把程式碼全部推倒重新去寫呢?這就需要我們通過設計模式來解耦了

下面講第一個簡單的模式---工廠模式

一、簡單的工廠模式

上面說了,怎麼用繼承和多型來對程式碼進行解耦合,增強複用性和擴充套件性呢?我們可以將運算子封裝成一個類,類裡面兩個屬性 第一次輸入的數字和第二次輸入的數字,提供get和set方法,並定義一個預設的getResult方法;

每一個運算子專門定義一個類,繼承上面父類,重寫計算結果方法,如下圖

最後提供一個工廠類來根據輸入的符號返回對應的物件例項

在main方法中測試

以後無論多少需求,只需要增加一個類,在工廠方法中增加一個例項即可。

 

二、策略模式

同樣先提個需求,做個超市收銀的系統,根據每個物品的單價和數量來計算出最後的總價格。(後期可能會加需求)

腦子裡是不是想著用上面的工廠模式去做呢? 建立個共同的父類,

定義一個獲取最終結果的方法,子類去繼承

然後通過工廠類獲取例項物件,最後輸出結果。

完全可以,但是現在超市雙十一搞活動,滿200便宜50,同時根據購物金額的大小有不同的打折,8.7.6.5折,這時候我們就發現客戶端的程式碼太臃腫了,這時候就用到策略模式。

 

策略模式是定義一系列演算法的方法,從概念上來看,所有這些演算法完成的都是相同的工作,只是例項不同,它可以以相同的方式呼叫不同的演算法,減少了各類演算法類與使用演算法類之間的耦合。

 

將結賬物件注入到Context中,同時構造方法限定了必須傳入條件才可以,按所傳入的條件選擇合適的結賬演算法,

最終的測試端程式碼如下

在客戶端的程式碼只剩下兩行,對於客戶端只需要明確型別和Context物件即可,剩下的演算法由Context來進行選擇,甚至連工廠都已經不用了,客戶端並不知道某個超類的存在。

 

三、單一職責原則

一個類而言,應該僅有一個引起它變化的原因

    簡單來說,一個類最好做一件事,當它負責的功能多了,就不可避免的會造成耦合度太高,牽一髮動全身。建議將相同邏輯相似功能的都獨立成類

    比如寫一個俄羅斯方塊,要藉助java圖形化來構建,還要寫業務邏輯判斷是否移動,監控按鍵並作出相應的響應。那這個時候就要考慮單一職責原則,將業務邏輯和圖形化業務分離開來,如果某天要從pc端移植到手機端,只需要修改圖形化的具體程式碼即可,業務邏輯程式碼完全可以直接使用。

軟體設計真正要做的許多內容,就是發現職責並把職責分別歸類,判斷一個類是否需要分離處理啊,就應該考慮如果你多於一個動機去改變這個類,那麼這個類就多一個職責

四、開放-封閉原則

簡單來說,是說軟體實體應該可以被擴充套件,但是不能被修改,對於擴充套件是開放的,對於更改是封閉的。

設計程式要儘量去滿足這一條件,但是絕對不是強制必須達到這個條件,因為需求總是不固定的,沒有完美的軟體設計,這條原則是要求我們在第一次需求更改後,將自己程式碼進行重構,再遇到類似的需求就可以直接擴充套件。主要是對程式碼以後的擴充套件性做一個提前的預想。

五、依賴倒轉

原話解釋是抽象不應該依賴細節,細節應該依賴抽象。

說白了就是面對介面程式設計,不要面對實現程式設計。