聊一聊設計模式(一)-- 六大原則

ClericYi發表於2020-02-21

聊一聊設計模式(一)-- 六大原則

前言

去年的11月份吧,我考下了中級軟體設計師的證照,裡面的必考題之一就是設計模式,雖然也沒有很難考,但是如果你是要去國企工作的讀者,其實我建議還是考上一考,一方面是對知識的複習,另一方面就是多少加一點工資。 以下附上一個報名的連結:bm.ruankao.org.cn/sign/welcom…

聊一聊設計模式(一)-- 六大原則

思維導圖

設計模式.png

六大原則

文章結構:定義 ---> 白話

單一職責原則

定義:就一個類而言,應該僅有一個引起它變化的原因。

其實字面意思就已經表達的比較明確,單一,也就是幹盡量少的事情。在HDU中可以對耦合和內聚程度的評判有一定的瞭解。 什麼叫做少,其實很難有一個標準。但是在Android的MVC框架中,Activity既作為View,又起著Controller的作用的時候是否顯得會很臃腫呢?他需要進行頁面的重新整理,網路處理,訊息處理等等,寫起來容易,但是在我們進行維護的時候,是不是會很頭疼呢。

開放封閉原則

定義:類,模組,函式等應該是可以擴充套件的,但是不可以修改。

在日常的專案開發中,需求一直是處於一個變動的狀態,但是這同樣也會成為專案開發的壁壘,如果你的Bean今天是一隻貓,明天就需要是一隻狗呢?重新打補丁嗎?顯然是一個很不合適的做法。而開放封閉原則,解決的就是這一類問題。不論是貓,還是狗,他們總會有相同的特徵,抽象化也就是這個原則實現的基礎。

// 定義一個動物抽象類
public abstract class Animal {
    abstract void do();
}
 
// 貓實現抽象方法
class Cat extends Animal {
    @Override
    void do() {
        System.out.println("喵");
    }
}
 
// 狗實現抽象方法
class Dog extends Animal {
    @Override
    void do() {
        System.out.println("汪");
    }
}
複製程式碼

里氏替換原則

定義:所有引用基類(一般來說都是抽象類或介面)的地方必須能透明的使用其子類的物件。

定義的具體含義就是將一個基類物件替換成其子類物件,程式將不會產生任何錯誤和異常,反過來則不成立,如果一個軟體實體使用的是一個子類物件的話,那麼它不一定能夠使用基類物件。 或者你還是不理解的話,以下兩段程式碼,就很清晰的解析了上述的含義。

List list = new ArrayList<String>();
ArrayList list = new List<String>();
複製程式碼

ArrayList作為我們擼程式碼日子裡的親人,你見過第二種寫法嗎? 接下來就是里氏替換原則的具體實現了。

/**
 * 基於里氏替換原則實現
 */
class Manage1 {
    private Animal animal;
 
    public void setAnimal(Animal animal) {
        this.animal = animal;
    }
 
    void getSound() {
        animal.do();
    }
}

/**
 * 使用子類實現
 */
class Manage2 {
    private Cat cat;
 
    public void setAnimal(Cat cat) {
        this.cat = cat;
    }
 
    void getSound() {
        cat.do();
    }
}
複製程式碼

以上基於兩種寫法,給予讀者評判,如果使用Manage2,如果我們希望獲得Dog的聲音,那麼就需要重新實現Manager3,然後差異就是隻是把Cat置換成Dog。而Manage1很好的解決了這個問題,因為不論是Cat還是Dog都是Animal的子類。

依賴倒置原則

定義:高層模組不應該依賴底層模組,兩者都應該依賴於抽象。抽象不應該依賴於細節,細節應該依賴於抽象。

兩個概念:

  • 抽象/高層模組:介面或者抽象類,一般只定義了有什麼操作,但是沒有具體實現。
  • 細節/底層模組:實現介面或者繼承抽象類而產生的,一般來說就是new出來的物件。

這裡的程式碼與里氏替換原則一致。

迪米特原則

定義:一個軟體實體應當少的與其他實體發生相互作用。

其實和上面的內容差不多,同樣都是為了降低耦合程度,直接用Demo證明就清楚明瞭了。

電話網路形式

  • 打電話的人 --> 接電話的人
  • 打電話的人 --> 中間服務商轉接 --> 接電話的人

第一種已經被時代拋棄了,雖然我們並不知覺,但是第一種電話網路模式,如果用在現代社會,那麼帶來的後果就是你再也看不見太陽了,頭頂密密麻麻的電話線,更何況那是座機互聯的時代,能夠靠電話線來解決,但是這個時代呢?移動互聯的時代呢,不能再靠著電話線來解決問題,而是中間商的介入就改變了這個現狀。

第一種電話網路模式

/**
 * 打電話的人
 */
class Call {
    private Receiver receiver;
 
    public void setReceicer(Receiver receiver) {
        this.receiver = receiver;
    }
 
    public void call() {
        receiver.receive();
    }
}

/**
 * 接電話的人
 */
class  Receiver{
    
    private String number;
    Receiver(String number){
         this.number = number;
    }
    
    public void receive() {
        System.out.println("接通電話");
    }
}

class Main{
    public static void main(String[] args) {
        Call call = new Call();
        call.setReceicer(new Receiver("電話號碼"));
        call.call();
    }
}
複製程式碼

第二種電話網路模式

/**
 * 轉接
 */
public abstract class Manager {
    abstract void link();
}
 
/**
 * 打電話的人
 */
class Call {
    private Manager manager;
    
    public void setManager(Manager manager) {
        this.manager = manager;
    }
 
    public void call() {
        manager.link();
    }
}
 
/**
 * 接電話的人
 */
class  Receiver{
    
    private String number;
    Receiver(String number){
         this.number = number;
    }
    
    public void receive() {
        System.out.println("接通電話");
    }
}

class CMCC extends Manager {
    private String number;
  
    CMCC(String number){
      this.number = number;
    }

    public void link() {
        System.out.println("連線接電話的人");
        Receiver receiver = new Receiver();
        receiver.receive();
    }
}

class Main{
    public static void main(String[] args) {
        Call call = new Call();
        call.setManager(new CMCC("電話號碼"));
        call.call();
    }
}
複製程式碼

這個時候兩個實體通過加入中間商的形式降低了耦合度。

介面隔離原則

定義:一個類對另一個類的依賴應該建立在最小的介面上

一個介面內要實現的函式數量可控,有那麼一點像資料庫裡的第一正規化。讓我們從Demo看看使用原則的與否的不同之處。

正常實現

// 特徵
interface Character {
    void look();
    void nature();
}

class Dog implements Character{
    @Override
    void look() {
        System.out.println("能看");
    }
    @Override
    void nature() {
        System.out.println("淘氣");
    }
}
複製程式碼

基於介面隔離原則實現

// 外觀
interface Facade {
     void look();
}
// 內在
interface Inherent {
    void nature();
}

class Dog implements Inherent{
    @Override
    void nature() {
        System.out.println("淘氣");
    }
}
複製程式碼

總結

七大原則其實表明的意思還是比較明確的,雖然可能寫法上的難度會有一定的增加,但是如果使用得當,後期的維護成本將會大大降低。

以上就是我的學習成果,如果有什麼我沒有思考到的地方或是文章記憶體在錯誤,歡迎與我分享。


相關文章推薦:

聊一聊設計模式(二)-- 建立型設計模式

聊一聊設計模式(三)-- 結構型設計模式

聊一聊設計模式(四)-- 行為型設計模式

相關文章