接口隔離原則

我的博客原文:
接口隔離原則java

景

設計模式六大原則之四:接口隔離原則。設計模式

簡介

姓名 :接口隔離原則ide

英文名 :Interface Segregation Principle測試

價值觀 :寧缺毋濫設計

我的介紹code

  1. Clients should not be forced to depend upon interfaces that they don't use.(客戶端不該該依賴它不須要的接口。)
  2. The dependency of one class to another one should depend on the smallest possible interface.(類間的依賴關係應該創建在最小的接口上。)

也用一個故事來說這 2 句乾巴巴的定義。接口

一小夥子跑到大城市的工廠打工,工做了一年半載,愈來愈以爲沒勁,天天干那麼多活,又領那麼一點工資,和他老爸抱怨這段時間的困擾,老爸想着,家裏有個小做坊,本身也一年不如一年了,要不就讓兒子回老家管理這小做坊。小夥子熬不過這個年,就跑回老家跟着老爸打理小做坊。ip

布娃娃
(來自Google Image)ci

小做坊主要是作布娃娃的,如上圖,工做在於打扮包裝布娃娃,工序有給布娃娃扎辮子、穿衣服、包裝入箱、打標籤。整個完整的流程都是一我的作的。有不少個工人天天都在作這個事情。開發

老爸向小夥子訴苦,感受招工挺多人的,生產力仍是提不上去。小夥子記着老爸的話,在工廠裏面觀察了幾天,他發現每一個工人都要作這 4 個打扮包裝布娃娃的工序,有些工人扎辮子很快但穿衣服很慢,有些工人扎辮子很慢但穿衣服快,他用了筆記本記下來:李大姨扎辮子快,王大媽穿衣服快,就這樣把每一個人有效率的工做都記錄下來。

一天晚上吃飯,小夥子跟老爸說了本身觀察到的現象,也把本子拿給老爸看,跟老爸商量:可不能夠作個嘗試,不要每一個人負責打扮包裝布娃娃全步驟,而是按工序分開,每一個人只負責一個工序,每一個工人只幹一件事,更容易熟能生巧。老爸聽着以爲有道理。

次日早上,就到小做坊裏,召集了全部工人,按小夥子的筆記上面的名單分工,你們都作好各自負責的內容,像流水線同樣,作好了就放到下個工序的地方,讓下個工序的人去作。到了下班,小夥子清點了今天工做的成果,包裝完成的娃娃比前一天多了 50% 。晚上小夥子跟老爸喝着百威吃起大肉慶祝一番。

這個故事你看了可能想罵爹罵娘,跟上面的定義有啥毛關係?故事只是把你們帶入這個場景,咱們在工做中,着手開發以前不都得先理清好需求背景,這就是要講接口隔離原則的背景,經過代碼來給你們講解一下如何用好接口隔離原則。

父親的運營模式

先看代碼

interface Work {

    void hairBraiding();
    void getDressed();
    void packingIntoTheBox();
    void makeTag();

}

class WangMather implements Work{

    @Override
    public void hairBraiding() {
        System.out.println("王大媽給布娃娃扎辮子");
    }

    @Override
    public void getDressed() {
        System.out.println("王大媽給布娃娃穿衣服");
    }

    @Override
    public void packingIntoTheBox() {
        System.out.println("王大媽把布娃娃裝入箱子");
    }

    @Override
    public void makeTag() {
        System.out.println("王大媽給箱子打標籤");
    }
}

class LiAunt implements Work {

    @Override
    public void hairBraiding() {
        System.out.println("李大姨給布娃娃扎辮子");
    }

    @Override
    public void getDressed() {
        System.out.println("李大姨給布娃娃穿衣服");
    }

    @Override
    public void packingIntoTheBox() {
        System.out.println("李大姨把布娃娃裝入箱子");
    }

    @Override
    public void makeTag() {
        System.out.println("李大姨給箱子打標籤");
    }
}

// 測試代碼
WangMather wangMather = new WangMather();
wangMather.hairBraiding();
wangMather.getDressed();
wangMather.packingIntoTheBox();
wangMather.makeTag();

LiAunt liAunt = new LiAunt();
liAunt.hairBraiding();
liAunt.getDressed();
liAunt.packingIntoTheBox();
liAunt.makeTag();

在父親管理下的小做坊,是你們各自完成好一個布娃娃,工做互不交接,在這種運營模式下,咱們把全部工做都合併在一個接口 Work 是沒有問題的。有人可能要問,不是說接口隔離麼?這裏面 Work 接口的 4 個方法均可以分離開,它們都是各自的工做內容。稍等一下,咱們如今是基於老父親運營的模式下實現,若是小做坊一直都是這種模式運營,這段代碼有問題麼?其實沒問題的,咱們根據當時的業務考慮,在這種狀況下,把 Work 抽成 4 個接口不是不能夠,只是不現實,每一個工人都去實現如出一轍的 4 個接口在老父親運營模式下是不切實際。

兒子的運營模式

接下來介紹兒子的運營模式。兒子提倡的是每一個工人職責分明,只負責一個事情,在這種狀況下,若是仍是用老父親的 Work 接口會有什麼問題呢?上面咱們說了,李大姨扎辮子快,王大媽穿衣服快,因此李大姨被分配去給布娃娃扎辮子,王大媽被分配去給布娃娃穿衣服。咱們沿用老父親的 Work 接口實現,代碼以下

class WangMather2 implements Work{

    @Override
    public void hairBraiding() {
    }

    @Override
    public void getDressed() {
        System.out.println("王大媽給布娃娃穿衣服");
    }

    @Override
    public void packingIntoTheBox() {
    }

    @Override
    public void makeTag() {
    }
}

class LiAunt2 implements Work {

    @Override
    public void hairBraiding() {
        System.out.println("李大姨給布娃娃扎辮子");
    }

    @Override
    public void getDressed() {
    }

    @Override
    public void packingIntoTheBox() {
    }

    @Override
    public void makeTag() {
    }
}

看出問題來了麼?李大姨僅僅參與扎辮子工做,王大媽參與了穿衣服工做,可是卻都要依舊實現其餘 3 個多餘的接口。因此在兒子的運營模式下,老父親的 Work 接口須要從新分配,以工序的角度分配,而不是以完成一個布娃娃的角度分配。總共有 4 個工序:扎辮子、穿衣服、包裝入箱、打標籤,咱們須要定義 4 個接口,讓員工去實現各自負責的工序接口。代碼以下

interface Hair {
    void hairBraiding();
}

interface Dress {
    void getDressed();
}

interface Box {
    void packingIntoTheBox();
}

interface Tag {
    void makeTag();
}

/**
 * 李大姨給布娃娃扎辮子快
 */
class LiAunt3 implements Hair {

    @Override
    public void hairBraiding() {
        System.out.println("李大姨給布娃娃扎辮子");
    }
}

/**
 * 王大媽給布娃娃穿衣服快
 */
class WangMather3 implements Dress{

    @Override
    public void getDressed() {
        System.out.println("王大媽給布娃娃穿衣服");
    }

}

/**
 * 陳大叔包裝快
 */
class ChenUncle implements Box {

    @Override
    public void packingIntoTheBox() {
        System.out.println("陳大叔給布娃娃裝箱");
    }
}

/**
 * 黃大姐貼標籤快
 */
class HuangSister implements Tag {

    @Override
    public void makeTag() {
        System.out.println("黃大姐給箱子打標籤");
    }
}

// 測試代碼
LiAunt3 liAunt3 = new LiAunt3();
WangMather3 wangMather3 = new WangMather3();
ChenUncle chenUncle = new ChenUncle();
HuangSister huangSister = new HuangSister();
liAunt3.hairBraiding();
wangMather3.getDressed();
chenUncle.packingIntoTheBox();
huangSister.makeTag();

這段代碼看起來就很清晰了,在兒子的運營模式下,你們都是隻作一道工序,這樣子實現就很是合理。看了這個過程,你理解了接口隔離原則了麼?再看一看上面的定義:客戶端不該該依賴它不須要的接口。閉上眼睛,靜默 3 秒,感覺一下。
咱們也能夠回憶一下在工做中編寫的代碼,是否是有遵照接口隔離原則?在特定的場景下,若是不少類實現了同一個接口,而且都只實現了接口的極少部分方法,這時候頗有可能就是接口隔離性很差,就要去分析能不能把方法拆分到不一樣的接口。

總結

接口隔離原則最最最重要一點就是要根據實際狀況,具體業務具體分析,不能犯了上面說到的錯誤:在老父親的運營模式下,按兒子的工序劃分接口去實現,那樣子會得不償失。

參考資料:《大話設計模式》、《Java設計模式》、《設計模式之禪》、《研磨設計模式》、《Head First 設計模式》

但願文章對您有所幫助,設計模式系列會持續更新,感興趣的同窗能夠關注公衆號,第一時間獲取文章推送閱讀,也能夠一塊兒交流,交個朋友。

公衆號之設計模式系列文章

公衆號

相關文章
相關標籤/搜索