设计模式原则
OVERVIEW
进行程序设计的时候,要尽可能地保证程序的可扩展性、可维护性和可读性,所以需要使用一些设计模式,这些设计模式都遵循了某些原则:
单一职责
类是一组相关属性和行为的集合,
- 封装指的就是将单一事物抽象出来组合成一个类,所以我们在设计类的时候每个类中处理的是单一事物而不是某些事物的集合。
- 设计模式中所谓的单一职责原则,就是对一个类而言,应该仅有一个引起它变化的原因(将这个类所承担的职责单一化)。
- 如果一个类承担的职责过耦合到了一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致设计变得脆弱,当变化发生时设计会遭受到意想不到的破坏。
- 软件设计要做的事情就是根据需求发现职责,并把这些职责进行分离、添加新的类,给当前类减负,这样的项目才容易维护。
开放封闭
开放封闭原则指的是软件实体(类、模块、函数等)可以扩展,但是不可以修改(对于扩展是开放的,对于修改是封闭的)。
该原则是程序设计的一种理想模式,在很多情况下无法做到完全的封闭,因此需要在这些位置创建抽象类来隔离以后发生的这些同类变化(多态的应用,创建新的子类并重写父类虚函数,用以更新处理动作)。此处的抽象类并不等价与C++中意义的抽象类(需要有纯虚函数),这里所说的抽象类只需要包含虚函数(纯虚函或非纯虚函数)能够实现多态即可。
开放封闭原则是面向对象设计的核心所在,这样可以给我们设计出的程序带来巨大的好处,使其可维护性、可扩展性、可复用性、灵活性更好。
依赖倒转
关于依赖倒转原则的描述:
- 高层模块不应该依赖低层模块,两个都应该依赖抽象。
- 抽象不应该依赖细节,细节应该依赖抽象。
概念 | 解释 |
---|---|
高层模块 | 可以理解为上层应用,就是业务层的实现 |
低层模块 | 可以理解为底层接口,比如封装好的 API、动态库等 |
抽象 | 指的就是抽象类或者接口,在 C++ 中没有接口,只有抽象类 |
里氏代换原则
里氏代换原则就是子类类型必须能够替换掉它们的父类类型。
关于这个原理的应用其实也很常见,比如在 Qt 中,所有窗口类型的类的构造函数都有一个 QWidget* 类型的参数(QWidget 类是所有窗口的基类),通过这个参数指定当前窗口的父对象。虽然参数是窗口类的基类类型,但是我们在给其指定实参的大多数时候,指定的都是子类的对象,其实也就是相当于使用子类类型替换掉了它们的父类类型。
该原则的要满足的第一个条件就是继承,还要求子类继承的所有父类的属性和方法对于子类来说都是合理的(合理的继承关系)。
在实际应用中使用子类替换掉父类,同时功能也不会受到影响,父类实现了复用,子类也能在父类的基础上增加新的行为,这个就是里氏代换原则。
- 抽象类中提供的接口是固定不变的
- 低层模块是抽象类的子类,继承了抽象类的接口,并且可以重写这些接口的行为
- 高层模块要实现某些功能,调用的是抽象类中的函数接口,并且是通过抽象类的父类指针引用其子类的实例对象(用子类类型替换父类类型),这样就实现了多态。
基于依赖倒转原则将项目结构重构后,低层模块发生变化,对应高层模块是没有任何影响的,代码更容易维护(依赖倒转原则就是对多态的典型应用)。