P2:開閉原則(OCP)

一、開閉原則簡介

開閉原則Open-Closed Principle,簡稱OCP,是面向對象的可複用設計中最重要的設計原則,具體定義如下:一個系統應當對擴展開放,對修改關閉,即軟件系統應在不修改原有功能代碼的情況下進行擴展(非必要時不輕易修改原有功能實現)。

遵循開閉原則的好處:
1、測試複用性:不影響原有的測試代碼,只需對擴展部分的代碼進行增量測試即可;
2、功能複用性:提高代碼的複用性,避免陷入重複造輪子的傾向;
3、維護成本:提高系統的可維護性,降低運維成本;

二、如何使用開閉原則;

1、面對抽象編程:

1)在構建系統架構的時候,按接口類來劃分功能,定義好接口的功能邊界,與接口定義無關的功能不允許放在接口中;
2)參數以及引用對象一律使用接口,而不是實現類;
3)接口抽象層保持穩定,不允許隨意修改;

2、元數據控制模塊行爲:

元數據(metadata)被定義爲:描述數據的數據,對數據及信息資源的描述性信息。
通俗來說就是通過配置文件來操作數據,Spring容器的控制反轉(Inversion of Control)就是一個典型的元數據控制模塊行爲的例子。
比較接近開發思維的解讀就是:類似變量的定義,我們通過使用配置參數來操作功能和數據,而不是直接更改接口實現類。

3、約定優先:

約定優於配置,我們在一個項目中事先建立項目章程,使用章程中指定了所有開發人員都必須遵守的約定,避免在後續的開發過程中出現功能或其他規範的越界行爲。

4、封裝變化

封裝變化,找出預計的變化或不穩定的點,爲這些變化點創建穩定的接口,準確的講是封裝可能發生的變化。開閉原則只是一個理想的狀態,它和物理學上“沒有摩擦”很類似,任何系統都無法百分之百做到“開閉”。但是,只要我們要朝着這個方向前進,就可以顯著的改善一個系統的架構,真正做到"擁抱變化"。

對變化的封裝包含兩層含義:
第一,將相同的變化封裝到一個接口中;
第二,將不同的變化封裝到不同的接口中,不應該有兩個不同的變化出現在同一個接口或抽象類中。

三、案例分析

假設某系統有一個支付功能,現有的支付方式有支付寶、微信支付,後期可能還有銀聯支付、易支付等等,原始的設計方案如下:


// 客戶端調用-選擇支付手段
public class CommonPay {
 
    void pay(String mode){
        if(mode.equals("ali")){
            AliPay aliPay = new AliPay();
            aliPay.pay();
        }else if(mode.equals("wx")){
            WXPay wxPay = new WXPay();
            wxPay.pay();
        }
    }
}
// 支付寶支付
public class AliPay {
    public void pay() {
        //TODO 調用支付寶支付
    }
}
// 微信支付
public class WXPay{
    public void pay() {
        //TODO 調用微信支付
    }
}

在上面的實現中,通過 commonPay.pay( 支付類型參數 ) 的方式傳入不同支付類型參數來調用對應的支付功能,如果我們要擴展銀聯支付、易支付等,就要對 commonPay.pay 的實現進行修改,不符合開閉原則。
我們按如下的方式進行一次改進:

public interface Pay {
    // 支付
    void pay();
}
public class AliPay implements Pay {
    @Override
    public void pay() {
        //TODO 調用支付寶支付
    }
}
public class WXPay implements Pay{
    @Override
    public void pay() {
        //TODO 調用微信支付
    }
}
// 客戶端調用-選擇支付手段
public class CommonPay {

    @Autowired
    Pay payMode;
    void pay(Pay payMode){
        payMode.pay();
    }
}

按這個模式,如果需要擴展銀聯支付,我們新增一個 UnionPay 的實現類,在CommonPay 的調用中傳入payMode=UnionPay 對象給pay方法即可:

public class UnionPay implements Pay{
	//TODO 
}

END.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章