OO设计中的一点心得
一个良好的OO设计必须具备可复用性、可扩展性、可维护性。
什么样的设计才是一个可复用性比较高的设计?
高内聚。我们把散落到各地的重复代码,都扫到一起,把他封装起来,通过职责的划分,将他们归类。单一职责的设计原则是实现高内聚的方法之一。
什么样的设计才是一个可扩展性比较高的设计?
低耦合。依赖接口不要依赖实现,依赖抽象不要依赖具体,最少依赖原则(只依赖第三者)等设计原则都是实现解耦的方法。
什么是解耦:调用者调用服务提供商的服务,我们说调用者与服务提供商是一种紧耦合关系。他们无法适应变化,如果今后更换了服务提供商,我们甚至需要来更改这部分代码。我们说过依赖接口不要依赖实现,依赖抽象不要依赖具体,这两个设计原则是实现解耦的方法。如果我们把服务抽象出来,让我们的调用者仅仅依赖高层的抽象,以后即使服务提供商有更换也无妨,因为我们的调用者根本不用关心服务的具体实现是谁,只要他们提供给我们服务的接口不变,调用者永远都不需要关心谁是最终的服务提供商,这就是解耦。
什么样的设计才是一个可维护性比较高的设计?
实现了可复用性与可扩展性的设计就是一个可维护性高的设计。
如何设计一个良好的OO设计?有哪些方法?
1、学习了解OO的基础。封装、继承、多态;
2、学习常用的设计模式;
3、学习了解常用的设计原则。
OO设计的精髓:将不变的抽象化,将变化的具体化
OO中实现复用的方法有哪些?他们各自的优缺点是什么以及他们各自适合的使用场景。
1、继承
通过直接继承一个类,我们的子类可以直接继承自父类的很多已经实现了的职责与方法,因此通过继承,我们能达到复用父类这部分代码的目的。
优点:继承可以很清晰的很真实的映射出现实生活中对象与对象的这种父子关系。
缺点:
a、JAVA语言不支持多继承(这应该不算是继承的一个缺点,继承不应该拘泥与编程语言,充其量只能说是JAVA当中继承的一个约束而已,至于是不是缺点,仁者见仁);
b、继承是一种编译期的行为,一旦编译过后就无法改变,我们在运行时无法更改其从父类中继承而来的行为;
c、子类一旦继承父类,就被迫接受父类中所有能够被继承的方法,而不论子类是不是想要继承的方法。(某些场景下,这应该算是继承的一个优点,但更多的时候看到的却是不好的一面,有人说可以通过覆盖父类中的方法来避免一些行为,如果是这样就不要使用继承,继承是为了实现重用的而非是为了覆盖,之后会专门讨论这个话题)
2、组合
我们把职责独立出专门的类族,外部对象通过引用最高层的抽象接口来实现复用。当我们需要复用这部分功能时,只需要委派我们引用接口的具体对象来完成调用即可。
优点:对于外部引用者来说,他们不需要关心也不知道具体执行者是谁,从而达到解耦的目的,方便今后扩展以适应更多的变化。同时组合可以在运行时灵活的变更其运行时的行为,通过setter方法,注入不同的实现类可完成并适应此类需求,而继承在运行时却是无法做到的。
缺点:可能会额外引入更多的类(关键是看我们对外的API接口是否有增加其复杂性和实用性,否则系统内部的话,引入额外的类问题不是很大,只要他们本身是合理的)。
组合是一种“HAS A”的关系,继承是一种“IS A”的关系。多用组合少用继承是设计原则之一。继承的目的也是为了组合。
OO中实现扩展的方法有哪些?
1、实现接口,继承父类。
2、委派、代理、装饰——可以参考代理模式和装饰者模式