《设计模式之美》理论二:如何做到“对扩展开放、修改关闭”?扩展和修改各指什么?

王争《设计模式之美》学习笔记

如何理解“对扩展开放、修改关闭”?

开闭原则

  • 开闭原则:SOLID 中的第二个原则,英文全称是 Open Closed Principle,简写为OCP。
  • 开闭原则是 SOLID 中最难理解、最难掌握,同时也是最有用的一条原则。
  • 对扩展开放、修改关闭,直接影响代码的扩展性,扩展性是代码质量最重要的衡量标准之一。

项目实战

  • API 接口监控告警的代码
  • Alert类:
    • 属性两个:AlertRule 存储告警规则,Notification 是告警通知类
    • 方法:check()主要业务逻辑两种报警场景
  • 此时要添加一种报警场景,修改:
    1. check()增加一个参数
    2. 在check()方法内部增加新报警场景的逻辑代码
    3. 修改单元测试
  • 用扩展的方案,要先重构Alert类:
    • 将check()方法的多参数,封装成ApiStatInfo 类
    • 引入handler概念,将多种报警场景放在各handler中
  • 此时要添加一种报警场景,扩展:
    1. 在ApiStatInfo 类中新增属性
    2. 添加一个新的报警场景的handler类
  • 重构后的代码十分灵活,添加新的报警场景,完全不需要修改check()的逻辑,只需要添加对应的handler即可。老的单元测试也不用修改,只需要添加新的单元测试。
  • 作者得例子都非常有实用场景,之前做过这样的报警,但是没把handler封装成类,而是封装的方法。

修改代码就意味着违背开闭原则吗?

  1. 当有新需求增加时,首先什么都不改不变是不可能的,好的方案和代码改动量大小无关
  2. 个人理解修改那就真的是在改,扩展实质都是在新增(模块、类、方法、属性)
  3. 到底是算修改还是扩展也跟你思考的粒度和单元有关系,要尽量通过增加属性、方法、类的方式
  4. 不要改动方法的内部逻辑

如何做到“对扩展开放、修改关闭”?

偏向顶层的指导思想

  1. 写代码的时候,多思考未开可能有哪些需求变更,设计代码结构留好扩展点,新的代码可能很灵活地插入扩展点
  2. 代码可变部分封装起来,隔离变化
  3. 代码不变部分抽象出来,以后扩展新的实现即可

具体方法论

  1. 最常用来提高代码扩展性的方法有:多态、依赖注入、基于接口而非实现编程。
  2. 文中举例,通过 Kafka 来发送异步消息:
    • 所有上层系统都依赖这组抽象的接口编程
    • 通过依赖注入的方式来调用
    • 当我们要替换新的消息队列的时候,写一个新的消息队列实现即可

如何在项目中灵活应用开闭原则?

  1. 写出支持“对扩展开放、对修改关闭”的代码的关键是预留扩展点。
  2. 业务导向的项目,要足够熟悉业务需求,才能知道当下和未开可能支持的业务需求。
  3. 如果跟业务无关,是偏底层的系统,需要了解系统将被如何使用,才能预估将来可能添加那些功能。
  4. 也不要过度设计,识别所有扩展点是不可能的,有些复杂的也可以到有需求驱动的时候,通过代码重构的方式实现。
  5. 代码的扩展性与可读性是冲突的,要根据实际情况权衡取舍。

你可能感兴趣的:(课程学习笔记)