面向对象编程的思想(5)未完成
合成/聚合复用原则是面向对象设计对象复用的主要形式
名称:合成/复用原则(Dependence Inversion Principle)DIP
核心:要依赖抽象,不要依赖于具体实现。换言之:通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,不相互影响,从而实现模块间的松散耦合。
规范:(1)每个类尽量都继承自接口或抽象类,或者二者都有。
(2)变量的显式类型尽量是接口或抽象类。
(3)类要尽量避免从具体类派生。
(4)尽量不要覆盖抽象基类中已实现的方法。
实现: (1)通过构造函数传递依赖对象
(2)通过setter方法传递依赖对象
(3)接口声明实现依赖对象
例子:例如我们设计一个Tutu类:
2 //图图是个女孩,会煮面
3 publicvoid cook(Noodles noodles){
4 noodles.eat();
5 }
6 }
设计一个Noodles类实现吃面条的行为:
2 //吃面条
3 publicvoid eat(){
4 System.out.println("吃面条!");
5 }
6 }
客户端测试代码:
2 publicstaticvoid main(String[] args){
3 Tutu tutu = new Tutu();
4 Noodles food =new Noodles();
5 tutu.cook(food);
6 }
7 }
运行结果:
吃面条!
这种设计方式就违反了依赖倒置原则,如果需要改变吃面的举动,就需要修改代码才能,不能单纯通过添加代码实现。标准方式如下(通过接口):
设计一个做饭的接口ITutu定义行为:
2 //这样就能做各种饭菜
3 publicvoid cook(IFood food);
4 }
设计一个Tutu类实现ITutu接口,实现动作行为:
2 @Override
3 publicvoid cook(IFood food){
4 food.eat();
5 }
6 }
设计一个IFood接口,定义eat方法:
2 publicvoid eat();
3 }
2 @Override
3 publicvoid eat(){
4 System.out.println("吃面条!");
5 }
6 }
设计一个Rice类实现IFood接口,重写eat动作行为:
2 @Override
3 publicvoid eat(){
4 System.out.println("终于可以吃米饭了!");
5 }
6 }
客户端测试代码:
2 publicstaticvoid main(String[] args){
3 //接口不能直接实例化,需要借助于类
4 ITutu tutu =new Tutu();
5 IFood rice =new Rice();
6 tutu.cook(rice);
7 IFood noodles =new Noodles();
8 tutu.cook(noodles);
9 }
10 }
~
运行结果:
吃面条!
请按 ENTER 或其它命令继续
在这个过程中,通过不同的类Noodles和Rice实现接口IFood,达到了不通过修改代码而使业务逻辑发生改变的方法。
总结:上边的MimiCat类作为Cat的子类,复用Cat和Animal的代码。并在父类的基础上添加新的行为。在面向对象的编程中,继承是抽象化的具体实现。
优点:开放封闭原则的核心是面向抽象编程,而不是面向具体编程,抽象是相对稳定的,让类依赖与抽象,对修改来说就是封闭的。面向对象编程中的继承及多态机制,可以实现对抽象体的继承,重写方法改变其固有行为,实现新的方法,达到扩展开放的目标。
后记:面向对象编程中,通过继承实现对类的扩展,实现封闭修改和扩展开发的目地。