第1章 软件架构设计原则
boss找leader统计course的数量,这是合成复用和最少知道(迪米特),
统计这个方法既可以统计course,也可以统计javaCourse和pythonCourse,这是里氏替换和依赖倒置,
统计这个方法只有统计功能,这是职责单一和接口隔离,
如果要做课程优惠,不修改course的price方法,而是写一个discountsCourse类,这是开闭原则。
学习设计原则是学习设计模式的基础。在实际开发过程中,并不要
求所有代码都遵循设计原则,我们要考虑人力、时间、成本、质量,不
能刻意追求完美,但要在适当的场景遵循设计原则,这体现的是一种平
衡取舍,可以帮助我们设计出更加优雅的代码结构。
1、开闭:对扩展开放,对修改关闭
它强调的是用抽象构建框架,用实现扩展细节,可以提高软件系统的可复用性及可维护性。
我们尽可能不修改源代码,但是可以增加新功能,比如不要修改某个方法,可以用增加子类继承父类并添加一个新的方法来达到目的
2、依赖倒置:设计代码结构时,高层模块不应该依赖低层模块,二者都应该依赖其抽象。抽象不应该依赖细节,细节应该依赖抽象。
通过依赖倒置,可以减少类与类之间的耦合性,提高系统的稳定性,提高代码的可读性和可维护性,并且能够降低修改程序所造成的风险。
以抽象为基准比以细节为基准搭建起来的架构要稳定得多,因此在拿到需求之后,要面向接口编程,先顶层再细节地设计代码结构。
3、单一职责:不要存在多于一个导致类变更的原因。这个的重点是:职责粒度的划分
假设我们有一个类负责两个职责,一旦发生需求变更,修改其中一个职责的逻辑代码,有可能导致另一个职责的功能发生故障。
如何解决这个问题呢?将两个职责用两个类来实现,进行解耦。后期需求变更维护互不影响。
这样的设计,可以降低类的复杂度,提高类的可读性,提高系统的可维护性,降低变更引起的风险。
总体来说,就是一个类、接口或方法只负责一项职责。
4、接口隔离:用多个专门的接口,而不使用单一的总接口,客户端不应该依赖它不需要的接口。
这个原则指导我们在设计接口时应当注意以下几点:
(1)一个类对另一个类的依赖应该建立在最小的接口之上。
(2)建立单一接口,不要建立庞大臃肿的接口。
(3)尽量细化接口,接口中的方法尽量少(不是越少越好,一定要适度)。
5、迪米特:又叫最少知道原则,指一个对象应该对其他对象保持最少的了解,尽量降低类与类之间的耦合度。
6、里氏替换:
如果对每一个类型为T1的对象o1,都有类型为T2的对象O2,
使得以T1定义的所有程序P在所有的对象O1都替换成O2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。
一个软件实体如果适用于一个父类,那么一定适用于其子类,所有引用
父类的地方必须能透明地使用其子类的对象,子类对象能够替换父类对
象,而程序逻辑不变。根据这个理解,引申含义为:子类可以扩展父类的功能,但不能改变父类原有的功能。
(1)子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
(2)子类可以增加自己特有的方法。
(3)当子类的方法重载父类的方法时,方法的前置条件(即方法的输入/入参)要比父类方法的输入参数更宽松。
(4)当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的输出/返回值)要比父类更严格或与父类一样。
7、合成复用:指尽量使用对象组合(has-a)/聚合(contanis-a)而不是继承关系达到软件复用的目的。