三个原则

SRP(单一职责原则)

就一个类来说,应该仅有一个引起它变化的原因。

如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者限制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受意想不到的破坏。
软件设计真正要做的许多内容其实就是发现职责并把那些职责互相分离。如果你能想到多于一个理由去修改一个类,那么这个类就有多于一个的职责。

举个例子

窗体程序俄罗斯方块,窗体程序和游戏逻辑应该是分离的。比如说如果要移植程序,那么在不同平台上只需要修改窗体类而不需要再去修改游戏逻辑的类。
写到这里的时候我想起了我自己写过的多功能日历
ValCalender。在这个用QT开发的程序里,虽然我已经尽量地进行了封装和创建了足够多的类,现在来反思我发现我封装的大多数还是窗口杂糅了对应功能的类,我的功能依赖于窗口实体,因此二者是杂揉的,没有符合单一职责原则,可移植性就很低了……🤔

OCP(Open-Close Principle)开放封闭原则

OCP认为软件实体应该是可扩展但是不可修改的。也就是说一方面对于扩展是开放的,另一方面对于更改是封闭的。尽管是理想化的原则,但是虽然不可能对于更改完全封闭,但是设计人员必须对于他设计的模块应该应对哪种变化封闭做出选择,构造抽象类来隔离那些最有可能发生的变化。从而实现这样一个效果:

程序的改动是通过增加新代码进行的,而不是更改现有的代码。

举个例子

讲工厂模式中提到的那个计算器程序,最开始就是完全把加法写死在客户端代码里了。这个时候要新增运算就得更改这些代码。对应的OCP操作就是构造一个抽象的运算类,通过继承多态等方式去隔离加减乘除和客户端。

OCP是面向对象的核心所在,遵循这个原则可以带来面向对象技术所声称的可维护、可扩展、可复用和灵活性好的好处。但是,拒绝不成熟的抽象和抽象本身一样重要……

依赖倒转原则

  • A:高层模块不应该依赖底层模块,两个都应该依赖抽象
  • B:抽象不应该依赖细节,细节应该依赖抽象
    B用白话说就是要针对接口编程,而不是针对实现编程
    而A怎么理解呢?举个例子,一个项目需要调用数据库,我们把数据库的调用写成函数,那么他就成为低层模块,项目就变成高层模块。但是如果我们发现一个新的项目,他的高层模块逻辑是和原来的项目是一样的,但是底层的需求却换了一个数据库或者数据的访问方式,这个时候原来的代码就没办法复用了……这个就是典型的高层模块依赖了底层模块。

所以按照A的要求,两者都应该依赖抽象而不是彼此。
所以依赖倒转就是说,除了约定的接口,大家谁也不要依赖谁,灵活自如。

LSP(里氏代换原则)

子类型必须能够替换掉他们的父类型。