程序設計6大原則

程序設計六大原則

2017年12月24日 22:57:20 LBJFxd 閱讀數:7603編程

 版權聲明:本文爲博主原創文章,轉載請註明出處! https://blog.csdn.net/fanxudonggreat/article/details/78888267緩存

1.單一職責網絡

簡單來講單一職責就是一個類只負責一個功能。更加具體的說就是對一個類而言,應該是一組相關性很高的函數、數據的封裝,是高內聚低耦合的,對外界而言應該僅有一個引發它變化的緣由。架構

單一職責在項目中的使用:框架

1.項目中的新手引導變量的管理能夠統一在各自的Modle中用單獨的類來管理ide

2.MVP模式P層生命週期與V層生命週期的同步能夠用單獨的包裝類來實現,函數

3.各類基礎框架功能的定義,例如:圖片的加載、緩存、顯示等都應該在各自的類中去作。this

下面以一個圖片加載庫的實現爲例:成功加載一張圖片可分爲:請求、緩存、加載三個步驟,那咱們就按照單一職責去建立三個類分別實現這三個功能url

/**
 * 圖片顯示
 */
public class ImageLoad {

    public void displayImage(String url, ImageView imageView) {

    }

}

/**
 * 圖片緩存
 */
public class ImageCache {

    public void put(String url,Bitmap bitmap){

    }

    public Bitmap get(String url){

    }

}

/**
 * 圖片加載
 */
public class ImageRequest {

    public Bitmap downloadImage(String url){

    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

上面的例子:ImageLoad只負責顯示圖片,ImageRequest負責從網絡下載圖片,ImageCache負責處理圖片緩存邏輯,這樣設計各自的類職責至關單一,假如咱們須要修改緩存的邏輯,咱們只須要修改ImageCache的邏輯,若項目升級咱們須要升級網絡請求庫,那涉及到圖片部分咱們也只須要修改ImageRequest類便可。總之:單一職責所要表達的用意就是」單一」二字,可是如何劃分一個類、甚至是一個函數的職責,這就須要每個開發者本身去設計。spa

2.開閉原則

開閉原則的英文全稱是Open Close Principle縮寫即OCP。開閉原則的定義是:軟件中的對象(類、模塊、函數等)應該對於擴展是開放的,可是對於修改是封閉的。在軟件的生命週期內,由於變化、升級和維護等緣由須要對軟件的原有代碼進行修改時,可能會將錯誤的代碼引入,從而破壞原有系統。所以當軟件需求發生變化時,咱們應該儘可能經過擴展的方式 來實現變化,而不是經過修改已有的代碼。

開閉原則在項目中的使用:

1.基類與子類,子類能夠繼承父類並擴展父類的功能

2.接口與實現類,接口定義功能,實現類按照各自的需求實現

繼續以上面的圖片加載框架爲例:上面咱們定義了三個類:ImageLoad,ImageRequest,ImageCache分別來作顯示、加載、緩存這三件事,很簡單的知足了單一職責的原則,可是當咱們不一樣狀況下須要執行不一樣的緩存策略時是否是每次又要去修改ImageCache這個類?這是否是跟咱們的開閉原則相違背?ImageRequest一樣如此。所以咱們須要保證在添加新的緩存策略時不須要修改原來的類,只須要在此基礎上擴展就能夠了,這樣就能夠避免修改原來的類引發的未知的錯誤。

/**
 * 圖片顯示
 */
public class ImageLoad {

    public void displayImage(String url, ImageView imageView) {

    }

}

/**
 * 圖片緩存
 */
public interface ImageCache {

    public void put(String url,Bitmap bitmap);

    public Bitmap get(String url);

}

/**
 * 圖片加載
 */
public interface ImageRequest {

    public Bitmap downloadImage(String url);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

注意:咱們只是將ImageCache類和ImageRequest類改爲了接口,這樣的好處就是咱們須要添加新的緩存策略時只須要實現ImageCache接口,ImageRequest一樣如此。下面咱們實現內存緩存和SD卡緩存

/**
 * 內存緩存
 */
public class MemoryCache implements ImageCache {

    @Override
    public void put(String url, Bitmap bitmap) {

    }

    @Override
    public Bitmap get(String url) {
        return null;
    }
}

/**
 * SD卡緩存
 */
public class DiskCache implements ImageCache {

    @Override
    public void put(String url, Bitmap bitmap) {

    }

    @Override
    public Bitmap get(String url) {
        return null;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

而後在咱們的ImageLoad中能夠動態注入ImageCahce實現:

/**
 * 圖片顯示
 */
public class ImageLoad {

    private ImageCache mCache = new MemoryCache();//默認緩存策略爲內存緩存

    /**
     * 緩存策略注入
     */
    public void setImageCache(ImageCache imageCache) {
        this.mCache = imageCache;
    }

    public void displayImage(String url, ImageView imageView) {

    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

在上面的例子中,經過setImageCache方法開發者能夠對ImageLoad注入不一樣的緩存實現,這使得ImageLoad更加簡單、健壯、擴展性、靈活性更高,同時也使得ImageCache的添加簡單高效(只須要實現ImageCache接口而後經過setImageCache注入),而且這些擴展不會不會致使ImageLoad類修改。這正是開閉原則的核心思想:對擴展開發,對修改封閉。

3.里氏替換原則

里氏替換原則的定義:若是對每個類型爲S的對象O1,都有類型爲T的對象O2,程序P在全部的對象O1都帶換成O2時,程序P的行爲沒有發生變化,那麼類型S是類型T的子類型換言之就是全部引用基類的地方必須能透明的使用其子類的對象。更通俗的講就是隻要父類出現的地方子類就能夠出現,並且替換爲子類也不會產生任何的錯誤或者異常。

里氏替換原則的核心是抽象,而抽象又依賴於繼承這個特性,在OOP當中,繼承的優缺點都至關明顯。

優勢:

1.代碼重用,減小建立類的成本,每一個子類都擁有父類的方法和屬性

2.子類與父類基本類似,但又與父類有所區別

3.提升代碼的可擴展性

缺點:

1.繼承是侵入性的,只要繼承就必須擁有父類的方法和屬性

2.可能形成子類代碼冗餘,靈活性下降,由於子類必須擁有父類的屬性和方法

在上面的例子中,咱們經過ImageCache創建起了一套緩存的規範,在經過setImageCache注入不一樣的具體實現,保證了系統的擴展性和靈活性。所以開閉原則和里氏替換原則每每是生死相依,如影隨行的,經過里氏替換原則來達到對擴展開放,對修改關閉的效果。

4.依賴倒置原則

依賴倒置原則指定了一種特定的解耦形式,使得高層次的模塊不依賴與低層次模塊的實現細節的目的,依賴模塊被顛倒了。依賴倒置原則有如下幾個關鍵點:

1.高層模塊不該該依賴於低層模塊,二者都應該依賴其抽象

2.抽象不該該依賴於細節

3.細節應該依賴於抽象

在Java語言中,抽象就是指接口或者抽象類,兩者都是不可以被直接實例化的:細節就是實現類,實現接口或者抽象類而產生的類就是細節,其特色就是能夠直接被實例化,也就是可使用關鍵字new產生一個對象。高層模塊就是指調用端,底層模塊就是指具體的實現類。依賴倒置原則在Java語言中的表現就是:模塊間的依賴經過抽象產生,實現類之間不發生直接的依賴關係,其依賴關係是經過接口或者抽象類產生的。使用一句話歸納就是:面向接口編程或者說是面向抽象編程。

若是類與類直接依賴細節,那麼這幾個類之間就有直接的耦合,當具體的需求發生變化是,意味着同時修改依賴者的代碼。在上面圖片加載的例子中,ImageLoad這個類依賴於ImageCache這個接口,而具體的實現能夠經過setImageCache注入,這樣當Cache策略須要升級時,只須要實現ImageCache接口,而後經過setImageCache注入到ImageLoad中。這樣就保證了細節與依賴的隔離。

5.接口隔離原則

接口隔離原則的定義是:客戶端不該該依賴於他不須要的接口。另外一種定義是:類之間的依賴關係應該創建在最小的接口上。接口隔離原則將很是龐大,臃腫的接口拆分紅更小的和更具體的接口,這樣客戶端將會值須要知道它們感興趣的方法。接口隔離原則的目的是系統解開耦合,從而容易重構、更改和部署。

在上面的IamgeLoad例子中,ImageCache指向ImageLoad提供了get和put方法,其餘一律無論,這使得具體的緩存策略實現對ImageLoad隱藏,這就是使用最小化接口隔離了實現類的細節,也促使咱們將更加龐大的接口拆分到更細粒度的接口當中,這一樣使得咱們的系統具備更低的耦合性、更高的靈活性。

6.迪米特原則

迪米特原則:一個對象應該對其餘對象有最少的瞭解,通俗的講,一個類應該對本身須要耦合或調用的類知道的最少,類的內部如何實現與調用者或者依賴者沒有關係,調用者或者依賴者只須要知道他須要的方法便可,其餘的一律無論。類與類之間的關係越密切,耦合度越大,當一個類發生改變時,對另外一個類的影響也越大。

在上面的圖片加載框架設計中,咱們的IamgeLoad只依賴於ImageCache的get和put方法,對其內部實現細節一無所知,即便經過setImageCache改變注入的對象時,ImageLoad也是對其內部實現細節不關心的,ImageLoad只關心ImageCache提供的get和put方法。這樣使得系統具備更加低的耦合性和更好的擴展性。

小結:

在應用開發過程當中,最難的不是完成應用的開發工做,而是在後續的升級、維護過程當中讓應用系統可以擁抱變化。擁抱變化也意味着在知足需求並且不破壞系統穩定的前提下保持高可擴展性、高內聚、低耦合,在經歷了各版本的變動以後依然保持着清晰、靈活、穩定的系統架構。

相關文章
相關標籤/搜索