《C++代码整洁之道》学习笔记,系列之六:面向对象
1. 面向对象思想
-
Simula-67被认为是第一个面向对象OO的编程语言
-
面向对象是一种思维方式,而不是所使用的编程语言本身的问题
2. 抽象
- 解决复杂问题的关键因素
3. 类的设计原则
-
(1)让类尽可能小
- ① 同样的,让函数尽可能小
- ② 理论上,一个类不要超过50行(Line of Code, 即LOC不超过50)
-
(2)单一职责原则 SRP = Single Responsibility Principle
- ① 单一职责原则是一个比LOC更好的标准。如果这些类没有违反SRP,那就完全没问题
-
(3)开闭原则 OCP
- ① 软件实体如模块、类、函数等,对拓展extension应该是开放的,但是对修改应该是封闭的
- ② 因为已有代码已经经过充分测试,如果任何新的需求都导致已有代码的修改,那将是致命的
- ③ 在面向对象中,继承是一种支持该原则的方法
-
(4)李氏替换原则LSP
- ① final关键字,一方面能避免函数在派生类中被重写,会报错;另一方面可以将类标记为final,不能将该类作为继承的基类
- ② 李氏替换原则意味着:派生类必须完全可以替代其基类,如通过继承长方形类来实现正方形类,对长宽关系进行了限制,这就违反了李氏替换原则
- ③ 李氏替换原则有以下规则:
-
- 基类不能在派生类中削弱
-
- 基类的不变量不能在派生类中更改
-
- 派生类中不应该在新引入的成员函数中改变不可变的成员
-
- ④ RTTI = Run-Time Type Information,运行时类型信息,是一种设计坏味道design smell,是不好的面向对象的软件设计
- ⑤ 在编程中,正方形不是矩形的子类型,违反了LSP。根据KISS原则,实现正方形最好的方法是,在矩形类中添加一个是否是正方形的查询方法即可;
- ⑥ 如果一定要实现正方形类,也不能继承矩形类,而应该从Shape虚基类继承;为了不违反DRY原则,使用矩形类的实例作为正方形类的内部实现,Rectangle impl,这种被称为"优先组合而非继承"
-
(5)接口隔离原则ISP = Interface Segregation Principle
- ① ISP接口隔离原则指出,接口不应该包含那些与实现类无关的成员函数。比如抽象鸟类实现Penguin类无法提供Bird::fly()的有效实现,却需要覆盖该成员函数
- ② ISP指出,我们应该将"宽接口"分离成更小且高度内聚的接口(角色接口),然后可以非常灵活地组合这些小的角色接口
-
(6)无环依赖原则
- ① 环依赖:两个类直接或间接地相互依赖,比如customer和account两个类
- ② 当形成环依赖时,问题显而易见,将会导致c++编译器错误
- ③ 将引用或指针与前置声明结合使用可以避免编译错误,但还是没有解决设计问题,那就是环依赖,这样的代码可能导致悬浮指针或其他未定义的行为,也没法进行独立测试
- ④ 类级别的环依赖导致对组件级别的环依赖
- ⑤ 无环依赖原则指出:组件或类的依赖图应该没有环。环依赖是紧耦合的一种不良表现形式,应不惜一切代价避免
-
(7)依赖倒置原则DIP
- ① DIP = Dependency Inversion Principle,依赖倒置原则
- ② DIP包含两个原则
-
- 高级模块不应依赖于低级模块,两者依赖于抽象
-
- 抽象不应依赖于细节,细节依赖于抽象
-
-
(8)不要和陌生人说话(迪米特法则)
- ① Law of Demeter,也称为最少知识原则。假定以下规则
-
- 允许成员函数调用类内其他成员函数
-
- 允许成员函数调用类内成员变量的成员函数
-
- 成员函数可以直接调用其参数的成员函数
-
- 成员函数可以调用局部对象的成员函数
-
- ② 迪米特法则,比如司机开车,司机不应直接去操作引擎内的燃油泵、点火系统和马达,司机对零部件的依赖应该取消。否则,如果内燃机被电力系统取代,那么必须调整司机类的视线,这违反了开闭原则,将引擎内部暴露在环境中违反了信息隐藏原则
- ③ 所以迪米特法则可以显著减少依赖性,降低耦合程度,并遵循信息隐藏原则和开闭原则
- ① Law of Demeter,也称为最少知识原则。假定以下规则
-
(9)避免"贫血类"
- ① 没有任何功能,全是数据存取setter/getter,严重违反了信息隐藏原则。这种类称为贫血类
-
(10)只说不问
- ① Tell, Don’t Ask
- ② 零件自己决定如何执行一个命令,而不是在上层处理零件的各种状态,这样分支数量众多,圈复杂度也高
-
(11)避免类的静态成员
- ① 静态成员函数偏向于面向过程的编程风格,在静态变量的协助下,破坏了封装,对象不再完全控制其状态
- ② 建议避免使用静态成员变量和静态成员函数
【参考文章】
[1]. C++代码整洁之道
created by shuaixio, 2024.11.17