《C++API 设计》4.6 类设计

摘抄于《C++API设计》4.6

类设计经验

80/20法则,把精力放在 定义了系统80%行为的20%的类上。

类设计上的选项:

  • 继承的使用:考虑类放在 现有继承层次结构中是否合适?公有继承还是私有继承?
  • 组合的使用:考虑 相对于继承,将关联的对象 作为 数据成员 是否 更合适?
  • 抽象接口的使用:设计抽象基类,子类重写各个纯虚成员函数?
  • 标准设计模式的使用:在类设计中采用 众所周知的设计模式
  • 初始化与析构模型:对象创建与删除,由客户通过new/delete实现?工厂方式管理?使用智能指针?
  • 定义复制构造函数和赋值操作符
  • 模板的使用:设计的类定义了一族的类型还是一种?
  • const 和 explicit的使用。参数、返回值、方法尽量定义为const。使用explicit 防止隐式类型转换
  • 是否需要定义操作符
  • 是否需要定义类型转换操作符
  • 友元的使用:会破坏类的封装,友元的出现往往是设计变坏的征兆
  • 非功能性约束:性能、内存的使用情况约束

使用继承的建议:

  • 明确 设计上支持还是禁止继承:如果支持,需要深入考虑哪些方法应该定义为 虚函数,并将行为记录在文档中。如果不支持,应将 其析构函数 声明为非虚
  • 仅在适当的地方使用继承:Liskov替换原则(LSP)
  • 避免深度继承树:深度继承结构增加设计复杂性,任何多于两层,三层 都是复杂的。
  • 使用纯虚成员函数强制子类提供实现
  • 不要为现有接口增加新的纯虚函数:会破坏客户代码
  • 不要过度设计:一个好的API是最小完备的,如 整个api中只有一个类继承它,对当前系统的需求而言 就是过度设计

Liskov替换原则:

用于指导一个类是否应该设计为另一个类的子类。指出 如果S是T的子类,那么行为上,S类型的对象不需要修改 就能 替换 T类型的对象。

组合 优先于 继承:

开闭原则OCP:

  • 为扩展而开发、为修改而关闭
  • 理念:一旦一个类创建完成并已向用户发布,唯一可以修改的只有编程错误。新特性的添加或功能的修改 应该通过 创建新类的方式实现
    但是,在实际的软件项目中OCP难以实现,系统发布后源代码永远不修改这一约束往往是不现实的,此外,任何行为变化都有创建新类这一规定 会 破坏原本清晰且最小化的设计。

因此OCP是一种 启发式的指导原则,而非必须遵守的原则。

可以将OCP重新理解为:类的接口为变化而关闭,而非接口背后的精确实现 不可改变。

API 应该为不兼容的接口变化而关闭,为功能扩展而开发。

迪米特法则:

又叫做最少知识原则。

指出:每个组件对其他组件 都只有有限的知识,甚至只知道与其紧密相连的组件的知识。意味着一个函数 只能做以下几个方面:

1.调用同一个类的其他函数

2.在同一个类的数据成员上调用函数

3.在它接受的任何参数上调用函数

4.在它创建的任何局部对象上调用函数

5.在全局对象上调用函数(不应该有全局变量)

错误例子:

迪米特法则指出,应该只调用自己类或直接相关对象的函数

posted @ 2021-03-15 15:30  Linese  阅读(180)  评论(0编辑  收藏  举报