面向对象七大基本原则

案例需求: 一个人想买一个电脑。

简单实现:

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大基本原则的理解,总结以下:单一原则,开闭原则,里氏替换,抽象接口,依赖倒置,迪米特法则

猜你喜欢

转载自www.cnblogs.com/pandapeter/p/10465068.html