1. 程式人生 > >面向對象七大基本原則

面向對象七大基本原則

網線 軟件 per end 顯示 基本原則 帶來 穩定性 添加

案例需求: 一個人想買一個電腦。

簡單實現:

class User {
    getComputer () {
        console.log(‘跑很遠去買220v電源‘),//表達的是這個過程很復雜,
        console.log(‘跑很遠買16存顯示器‘)
        //。。。。。
        console.log(‘組裝‘);
    }
};
new User().getComputer();

上面的實現滿足了我的需求。但是有個問題:在getComputer方法中,每次都要跑很遠去買,然後自己組裝,整個過程繁瑣復雜(腦補getComputer方法內部的代碼很長很長)。如果能有人送貨,就好了。

解決思路就是單一原則: 一個類或方法只做一件事。

class User {
    dianyuan(num) {
        console.log(`買了個${num}v電源`)
    }
    screen(num) {
        console.log(`買了個${num}寸顯示器`)
    }
    zz() {
       console.log(‘組裝‘) 
    }
    getComputer () {
        this.dianyuan(220);
        this.screen(20);
        
        //。。。。。
        this.zz();
    }
};
new User().getComputer();

 在新實現中,我隨便打幾個電話(將不同類型的零件單獨定義為各自的函數,調用dianyuan/screen...,實現單一原則),就能得到想要類型的零件。但是,不是每個人都像我這樣了解電腦零件及組裝過程的,對於小白來說,它希望有個經銷商能直接幫他完成零件購買及組裝的過程,

解決思路:再次使用單一原則

class Computer {
    dianyuan() {
        console.log(`買了個200v電源`)
    }
    screen(num) {
        console.log(`買了個17寸顯示器`)
    }
    all() {
        this.dianyuan();
        this.screen();
    }
}
class User {
    
    zz() {
       console.log(‘組裝‘) 
    }
    getComputer () {
        let computer = new Computer(220, 20);
        computer.all();
        this.zz();
    }
};
new User().getComputer();

  

  這次實現中, 我將獲取零件的過程封裝成了一個類,它能返回組裝一個電腦所需要的所有零件;從此小白獲取一個電腦的方法就是調用以下Computer.all()方法。但是只有一個經銷商實在是太被動了,我不能貨比三家,我希望所有的經銷商都具備獲取所有零件的能力,但是各自零件的類型及價錢又能讓我可以選擇。

解決思路:

1抽象:抽取事物的本質,剔除具體表現。

2裏氏替換:子類能夠出現在所有父類出現的地方。

3依賴倒置:程序應該依賴抽象接口, 而不依賴具體實現。

class SuperComputer {
    dianyuan() {

    }
    screen() {

    }
    all() {
        this.dianyuan();
        this.screen();
    }
}

class SubOneComputer extends SuperComputer{
    dianyuan() {
        console.log(‘我們家的220電源10元‘)
    }
    screen() {
        console.log(‘我們家17屏幕20元‘);
    }
}

class SubTwoComputer extends SuperComputer {
    dianyuan() {
        console.log(‘我們家的220電源20元‘)
    }
    screen() {
        console.log(‘我們家17屏幕10元‘);
    }
}

class User {
    
    zz() {
       console.log(‘組裝‘) 
    }
    getComputer (computer) {
        //為了程序的健壯性, 你需要判斷這個參數是否是某經銷商的實例(能夠調用all()),從而產生某個經銷商的依賴, 然後最好的實現方式就是判斷它是否是某個抽象類的實例,避免對擴展子類的依賴, 這就是依賴倒置原則
        if (computer instanceof SuperComputer) {
            computer.all();
            this.zz();
        } else {
            console.log(‘請傳入經銷商的實例‘)
        }
    }
};
let  xiaoming= new User();
xiaoming.getComputer(new SubOneComputer());
let xiaohong = new User()
xioahong.getComputer(new SubTwoComputer());

  小紅/小明通過不同經銷商那拿到不同類型的零件,但是零件肯定是齊全的,這得力於兩點。

1:抽象類SuperComputer為所有的經銷商定義了標準(是不是有點抽象接口的概念)。

2:經銷商實現了SuperComputer定義的所有零件方法。這就是裏氏替換帶來的好處。

3:為了User.getComputer()的健壯性, 你需要判斷computer是否是某經銷商的實例(能夠調用all()),從而產生某個經銷商的依賴, 然後最好的實現方式就是判斷它是否是某個抽象類的實例,從而避免對擴展子類的依賴,畢竟抽象類的最可靠。

然後 而不然後經銷商又了新的問題, 為了盈利,他必須擴大業務範圍。

解決思路:

開閉原則:對修改關閉, 對擴展開放

class SuperComputer {
    dianyuan() {

    }
    screen() {

    }
    all() {
        this.dianyuan();
        this.screen();
    }
}

class SubOneComputer extends SuperComputer{
    dianyuan() {
        console.log(‘我們家的220電源10元‘)
    }
    screen() {
        console.log(‘我們家17屏幕20元‘);
    }

    paper() {
        console.log(‘A4紙1毛一張‘)
    }
}

class SubTwoComputer extends SuperComputer {
    dianyuan() {
        console.log(‘我們家的220電源20元‘)
    }
    screen() {
        console.log(‘我們家17屏幕10元‘);
    }

    netline() {
        console.log(‘網線1米2元‘)
    }
}

class User {
    
    zz() {
       console.log(‘組裝‘) 
    }
    getComputer (computer) {
        //為了程序的健壯性, 你需要判斷這個參數是否是某經銷商的實例(能夠調用all()),從而產生某個經銷商的依賴, 然後最好的實現方式就是判斷它是否是某個抽象類的實例,避免對擴展子類的依賴, 這就是依賴倒置原則
        if (computer instanceof SuperComputer) {
            computer.all();
            this.zz();
        } else {
            console.log(‘請傳入經銷商的實例‘)
        }
    }
};
let  xiaoming= new User();
xiaoming.getComputer(new SubOneComputer());
let xiaohong = new User()
xioahong.getComputer(new SubTwoComputer());

  上面的兩個經銷商為了利潤, 各自擴大了經營範圍(paper(), netline()),他們是對SupterComputer的擴展,而不能為單獨的經銷商在SuperComputer類中去添加跟電腦零件無關的方法,保證抽象的單一性,穩定性。

還有一個問題, 現在所有的小白能輕松的從不同的經銷商那裏獲取全部零件,但是還是要自己組裝, 還不夠方便,其實小白們只需要找到一個會組裝的人,這個組裝的人肯定對於電腦零件是非常熟悉的,小白們不在關心電腦零件問題,。

解決思路:

迪米特法則:一個對象應該對其他對象保持最少的了解

class SuperComputer {
    dianyuan() {

    }
    screen() {

    }
    all() {
        this.dianyuan();
        this.screen();
    }
}

class SubOneComputer extends SuperComputer{
    dianyuan() {
        console.log(‘我們家的220電源10元‘)
    }
    screen() {
        console.log(‘我們家17屏幕20元‘);
    }

    paper() {
        console.log(‘A4紙1毛一張‘)
    }
}

class SubTwoComputer extends SuperComputer {
    dianyuan() {
        console.log(‘我們家的220電源20元‘)
    }
    screen() {
        console.log(‘我們家17屏幕10元‘);
    }

    netline() {
        console.log(‘網線1米2元‘)
    }
}

//組裝類
class InitComputer {
    software() {
        console.log(‘安裝軟件‘)
    }
   
    hardware(computer) {
        if (computer instanceof SuperComputer) {
            computer.all();
        } else {
            console.log(‘請傳入經銷商的實例‘)
        }
    }
    zz(money) {
        switch(money)
        {
            case 5000: 
                this.hardware(new SubOneComputer());//5000元的配置
            case 4000:
                this.hardware(new SubTwoComputer());//4000元的配置
        }
        this.software();
        console.log(‘組裝完畢‘);
    }
}
class User {
    
    getComputer (money) {
        new InitComputer().zz(money);
    }
};
let  xiaoming= new User();
xiaoming.getComputer(4000);
let xiaohong = new User()
xioahong.getComputer(5000);

  終於搞定了,現在小白只需要給組裝類money就能得到一臺相應配置的電腦, 不用在找經銷商及自己組裝了。這就是迪米特法則, 小白不需要熟悉經銷商的套路,而是通過組裝類這個中間人去搞定。

以上的例子是我對公司培訓面向對象6大基本原則的理解,總結以下:單一原則,開閉原則,裏氏替換,抽象接口,依賴倒置,迪米特法則

面向對象七大基本原則