偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

聊聊設(shè)計(jì)模式中的里式替換

開發(fā) 前端
依賴倒置原則是OO設(shè)計(jì)的核心原則,設(shè)計(jì)模式的研究和應(yīng)用是以依賴導(dǎo)致原則為知道原則的,在知識(shí)星球中的設(shè)計(jì)模式中我們將會(huì)一一給大家體現(xiàn)。

一、前言

在面向?qū)ο蟮能浖O(shè)計(jì)中,只有盡量降低各個(gè)模塊之間的耦合度,才能提高代碼的復(fù)用率,系統(tǒng)的可維護(hù)性、可擴(kuò)展性才能提高。面向?qū)ο蟮能浖O(shè)計(jì)中,有23種經(jīng)典的設(shè)計(jì)模式,是一套前人代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié),如果把設(shè)計(jì)模式比作武功招式,那么設(shè)計(jì)原則就好比是內(nèi)功心法。常用的設(shè)計(jì)原則有七個(gè),具體如下:

  • 單一職責(zé)原則:專注降低類的復(fù)雜度,實(shí)現(xiàn)類要職責(zé)單一;
  • 開放關(guān)閉原則:所有面向?qū)ο笤瓌t的核心,設(shè)計(jì)要對(duì)擴(kuò)展開發(fā),對(duì)修改關(guān)閉;
  • 里式替換原則:實(shí)現(xiàn)開放關(guān)閉原則的重要方式之一,設(shè)計(jì)不要破壞繼承關(guān)系;
  • 依賴倒置原則:系統(tǒng)抽象化的具體實(shí)現(xiàn),要求面向接口編程,是面向?qū)ο笤O(shè)計(jì)的主要實(shí)現(xiàn)機(jī)制之一;
  • 接口隔離原則:要求接口的方法盡量少,接口盡量細(xì)化;
  • 迪米特法則:降低系統(tǒng)的耦合度,使一個(gè)模塊的修改盡量少的影響其他模塊,擴(kuò)展會(huì)相對(duì)容易;
  • 組合復(fù)用原則:在軟件設(shè)計(jì)中,盡量使用組合/聚合而不是繼承達(dá)到代碼復(fù)用的目的。

這些設(shè)計(jì)原則并不說(shuō)我們一定要遵循他們來(lái)進(jìn)行設(shè)計(jì),而是根據(jù)我們的實(shí)際情況去怎么去選擇使用他們,來(lái)讓我們的程序做的更加的完善。

之前我們看了單一職責(zé)原則和開閉原則,今天我們一起來(lái)聊聊里式替換原則和依賴倒置原則,千萬(wàn)別小看這些設(shè)計(jì)原則,他在設(shè)計(jì)模式中會(huì)有很多體現(xiàn),所以理解好設(shè)計(jì)原則之后,那么設(shè)計(jì)模式,也會(huì)讓你更加的好理解一點(diǎn)。

二、里式替換原則

里式替換原則,簡(jiǎn)單的說(shuō):如果對(duì)每一個(gè)類型為T1的對(duì)象o1,都有類型為T2的對(duì)象o2,使得以T1定義的所有程序P在所有的對(duì)象o1都代換成o2 時(shí),程序P的行為沒(méi)有發(fā)生變化,那么類型 T2 是類型 T1 的子類型。

換句話來(lái)說(shuō),一個(gè)軟件實(shí)體如果使用一個(gè)基類的話,那么一定適用于其子類,而且它根本不會(huì)察覺(jué)出基類對(duì)象和子類對(duì)象的區(qū)別。

比如說(shuō),假設(shè)有兩個(gè)類,一個(gè)是Base類,另一個(gè)是Derived類,并且Derived類是Base的子類,那么一個(gè)方法如果可以接受一個(gè)基類對(duì)象b的話:method(Base b),那么它必然可以接受一個(gè)子類對(duì)象d,可以有 method1(d)。

里式替換原則是繼承復(fù)用的基石,只有當(dāng)衍生類可以替換掉基類,軟件單位的功能不會(huì)受到影響的時(shí)候,基類才能真正被復(fù)用,而衍生類也才能夠在基類的基礎(chǔ)上增加新的行為。

我們通過(guò)一個(gè)例子來(lái)理解一下:

《西游記》中,美猴王下地府橋段,個(gè)位應(yīng)該有印象把,到達(dá)閻王殿之后,拿到生死簿,把生死簿上所有的包括自己,還有其他的獼猴,所有的猴子猴算都給劃了,這也是導(dǎo)致之后真假美猴王橋段的前序。

畫個(gè)圖理解:

圖片圖片

很顯然,地府管理一切生靈的生死的方法都是通過(guò)類來(lái)進(jìn)行區(qū)分的,比如孫悟空就是石猴,之后出現(xiàn)的那個(gè)六耳獼猴就是獼猴,但是他們都是屬于同一個(gè)類,猴類,就像下圖中。

圖片圖片

因此,孫悟空把猴類中有姓名的都從生死簿勾掉之后,顯然是因?yàn)楣椿晷」韨儾⒉粎^(qū)分石猴類與獼猴類,就像下圖:

圖片圖片

換句話來(lái)說(shuō),只要是猴類適用的,獼猴和石猴都適用,這其實(shí)就是里式替換原則。

這是第一種解釋,還有第二個(gè)更加通俗易懂的解釋:所有引用基類的地方必須能透明地使用其子類的對(duì)象。

第二種定義比較通俗,容易理解:只要有父類出現(xiàn)的地方,都可以用子類來(lái)替代,而且不會(huì)出現(xiàn)任何錯(cuò)誤和異常。但是反過(guò)來(lái)則不行,有子類出現(xiàn)的地方,不能用其父類替代。

public class TestA {
    public void fun(int a,int b){
        System.out.println(a+"+"+b+"="+(a+b));
    }
    public static void main(String[] args) {
        System.out.println("父類的運(yùn)行結(jié)果");
        TestA a=new TestA();
        a.fun(1,2);
        //父類存在的地方,可以用子類替代
        //子類B替代父類A
        System.out.println("子類替代父類后的運(yùn)行結(jié)果");
        TestB b=new TestB();
        b.fun(1,2);
    }
}
class TestB extends TestA{
    @Override
    public void fun(int a, int b) {
        System.out.println(a+"-"+b+"="+(a-b));
    }
}

大家肯定也都能猜出來(lái)結(jié)果是什么樣子的。

父類的運(yùn)行結(jié)果
1+2=3
子類替代父類后的運(yùn)行結(jié)果
1-2=-1
Process finished with exit code 0

我們想要的結(jié)果是“1+2=3”??梢钥吹剑椒ㄖ貙懞蠼Y(jié)果就不是了我們想要的結(jié)果了,也就是這個(gè)程序中子類B不能替代父類A。這違反了里氏替換原則原則,從而給程序造成了錯(cuò)誤。

子類中可以增加自己特有的方法

這個(gè)很容易理解,子類繼承了父類,擁有了父類和方法,同時(shí)還可以定義自己有,而父類沒(méi)有的方法。這是在繼承父類方法的基礎(chǔ)上進(jìn)行功能的擴(kuò)展,符合里氏替換原則。

public class TestA {
    public void fun(int a,int b){
        System.out.println(a+"+"+b+"="+(a+b));
    }

    public static void main(String[] args) {
        System.out.println("父類的運(yùn)行結(jié)果");
        TestA a=new TestA();
        a.fun(1,2);
        //父類存在的地方,可以用子類替代
        //子類B替代父類A
        System.out.println("子類替代父類后的運(yùn)行結(jié)果");
        TestB b=new TestB();
        b.fun(1,2);
        b.newFun();
    }
}
class TestB extends TestA{
    public void newFun(){
        System.out.println("這是子類的新方法...");
    }
}

這次運(yùn)行出來(lái)的代碼結(jié)果就是我們意料中的內(nèi)容了。

父類的運(yùn)行結(jié)果
1+2=3
子類替代父類后的運(yùn)行結(jié)果
1+2=3
這是子類的新方法...
Process finished with exit code 0

JAVA語(yǔ)言對(duì)里式替換原則支持的局限:

JAVA編譯器的檢查是有局限性的,為什么呢?舉個(gè)例子來(lái)說(shuō),描述一個(gè)物體大小的量有精度和準(zhǔn)確度兩種屬性。所謂的精度,就是這個(gè)量的有效數(shù)字有多少位;而所謂的精準(zhǔn)度,是這個(gè)量與真實(shí)的物體大小相符合到什么程度。

一個(gè)量可以有很高的精度,但是卻無(wú)法與真實(shí)物體的情況相吻合,JAVA語(yǔ)言編譯器能夠檢查的,僅僅是相當(dāng)于精度的屬性而已,它沒(méi)有辦法去檢查這個(gè)量與真實(shí)物體的差距。

換一句話來(lái)說(shuō),JAVA編譯器不能檢查一個(gè)系統(tǒng)在實(shí)現(xiàn)和商業(yè)邏輯上是否滿足里式替換原則。

三、依賴倒置原則

如果說(shuō)實(shí)現(xiàn)開閉原則的關(guān)鍵事抽象化,是面向?qū)ο笤O(shè)計(jì)的目標(biāo)的話,依賴倒置原則就是這個(gè)面向?qū)ο笤O(shè)計(jì)的主要機(jī)制。

依賴倒置原則,簡(jiǎn)單的說(shuō):抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)當(dāng)依賴于抽象。換言之,要針對(duì)接口編程,而不是針對(duì)實(shí)現(xiàn)編程。

為什么要實(shí)現(xiàn)倒置?這也是我們看這個(gè)定義的時(shí)候產(chǎn)生的一些問(wèn)題,那么我們就來(lái)說(shuō)說(shuō)。

簡(jiǎn)單的來(lái)說(shuō),傳統(tǒng)的過(guò)程性系統(tǒng)的設(shè)計(jì)辦法傾向于使高層次的模塊依賴于低層次的模塊,抽象層依賴于具體層次,倒置原則是要把這個(gè)錯(cuò)誤的依賴關(guān)系倒轉(zhuǎn)過(guò)來(lái),這就是依賴倒置原則的由來(lái)。也是為什么要進(jìn)行依賴倒置。

依賴倒置原則的實(shí)現(xiàn)方法

依賴倒置原則的目的是通過(guò)要面向接口的編程來(lái)降低類間的耦合性,所以我們?cè)趯?shí)際編程中只要遵循以下4點(diǎn),就能在項(xiàng)目中滿足這個(gè)規(guī)則:

  • 每個(gè)類盡量提供接口或抽象類,或者兩者都具備。
  • 變量的聲明類型盡量是接口或者是抽象類。
  • 任何類都不應(yīng)該從具體類派生。
  • 用繼承時(shí)盡量遵循里氏替換原則。

下面我們通過(guò)一些代碼實(shí)例(商品售賣)來(lái)進(jìn)行理解:

class BeijingShop implements Shop{
        public String sell(){
            return "北京商店售賣:北京烤鴨,稻香村月餅";
        }
    }
    class ShanDongShop implements  Shop{
        @Override
        public String sell() {
            return "山東商店售賣:德州扒雞,煙臺(tái)蘋果";
        }
    }
    //如果說(shuō)顧客去購(gòu)買商品
class Customer{
    public void shopping(ShanDongShop shop){
        //購(gòu)物
        System.out.println(shop.sell());
    }
}
//這是在山東商店購(gòu)買,如果說(shuō)是在北京商店購(gòu)買就會(huì)這樣
class Customer{
    public void shopping(BeijingShop shop) {
        //購(gòu)物
        System.out.println(shop.sell());
    }
}

這也是這種設(shè)計(jì)的存在缺陷,顧客每更換一家商店,都要修改一次代碼,這明顯違背了開閉原則。存在以上缺點(diǎn)的原因是:顧客類設(shè)計(jì)時(shí)同具體的商店類綁定了,這違背了依賴倒置原則。解決方式我們可以定義一個(gè)共同的接口Shop,就可以這樣了。

public class TestSale {
    public static void main(String[] args) {
        Customer c = new Customer();
        System.out.println("---顧客購(gòu)買商品如下---");
        c.shopping(new ShanDongShop());
        c.shopping(new BeijingShop());
    }
}

interface Shop{
    //售賣方法
    public String sell();
}

class BeijingShop implements Shop{
    public String sell(){
        return "北京商店售賣:北京烤鴨,稻香村月餅";
    }
}

class ShanDongShop implements  Shop{
    @Override
    public String sell() {
        return "山東商店售賣:德州扒雞,煙臺(tái)蘋果";
    }
}

class Customer{
    public void shopping(Shop shop) {
        System.out.println(shop.sell());//購(gòu)物
    }
}

程序運(yùn)行結(jié)果:

---顧客購(gòu)買商品如下---
山東商店售賣:德州扒雞,煙臺(tái)蘋果
北京商店售賣:北京烤鴨,稻香村月餅
Process finished with exit code 0

這樣,不管顧客類 Customer 訪問(wèn)什么商店,或者增加新的商店,都不需要修改原有代碼了。

依賴倒置原則是OO設(shè)計(jì)的核心原則,設(shè)計(jì)模式的研究和應(yīng)用是以依賴導(dǎo)致原則為知道原則的,在知識(shí)星球中的設(shè)計(jì)模式中我們將會(huì)一一給大家體現(xiàn)。

責(zé)任編輯:武曉燕 來(lái)源: Java極客技術(shù)
相關(guān)推薦

2024-12-09 08:18:33

2024-10-06 12:56:36

Golang策略設(shè)計(jì)模式

2025-05-09 09:05:00

Spring框架設(shè)計(jì)模式

2023-03-21 07:57:37

Go語(yǔ)言設(shè)計(jì)模式

2021-12-28 19:05:41

路由服務(wù)治理

2024-01-31 08:41:43

異步設(shè)計(jì)項(xiàng)目

2023-11-07 12:00:05

分布式系統(tǒng)數(shù)據(jù)訪問(wèn)

2025-05-22 08:15:00

2023-01-04 09:37:16

2022-12-14 08:06:08

2025-03-20 09:54:47

2024-07-05 08:26:54

2025-06-16 08:22:23

2012-08-30 09:07:33

設(shè)計(jì)模式

2022-09-07 08:18:26

分布式灰度方案分支號(hào)

2021-04-18 21:07:32

門面模式設(shè)計(jì)

2010-11-26 16:17:48

設(shè)計(jì)模式JDK

2024-07-31 08:12:33

2012-04-10 10:04:26

并行編程

2012-12-25 09:38:41

JavaScript設(shè)計(jì)模式
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)