`
ohmygodlzl
  • 浏览: 21409 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

OOD之开放封闭原则

阅读更多
这个系列是早前发布在部门wiki上的,引导组里的兄弟入门OOD,希望同样对刚刚走到OOD门前的同学有用。

    在探讨单一职责原则(SRP)时,我用黑体强调了一句话:如果你接到一个需求后发现需要修改一个已经存在的类,那就要考虑一下是不是原来的设计不合理,没有把应该独立出来的职责分离出来。我说这话的依据就是开放封闭原则――软件实体(类,模块,函数等)应该是可以扩展的,但是不可修改的
     这里的不可修改不是说无论什么原因都不许改,代码中有bug还是要改的,而且实现一个不可修改的类往往需要一个演进的过程,用Bob叔叔(Robert C. Martin,人称Bob叔叔)的话说就是:我们愿意被第一颗子弹击中,然后我们会确保自己不再被同一只枪发射的其他任何子弹击中。――这也有点像圣斗士的哲学:同一招对圣斗士而言不要用两次(因为圣斗士都遵循OCP原则)。
    回想一下上次提到的校验码的例子,在最初那个一笼统的设计下,当需求进化了,要求校验码文本不能是纯数字时,我们被第一颗子弹击中了,我们知道校验码文本的生成是一只枪,不远的将来还可能还会发射别的子弹,所以我们修改了VerifyCodeGenerateImpl的实现,通过抽象出一个RandomTextGenerator接口来隔离这种变化。注意,我们还是修改了一些代码,但我们保证了不会再因为校验码文本生成逻辑的变化修改VerifyCodeGenerateImpl类,取而代之的是通过添加新的RandomTextGenerator子类来实现新的校验码文本生成逻辑。

    从校验码的例子我们可以看出,抽象是实现OCP原则的关键。抽象本身必须是稳定的,可以是接口,也可以是抽象类,宗旨是要把可能变化的逻辑推迟到子类中去实现。但使用了接口并不代表我们就遵循了OCP,抽象的关键在于对具体的变化纬度――也就是职责的分离和封装,也就是需要与单一职责原则结合使用。打个比方,我们现在采用Spring做开发,Spring鼓励面向接口编程,我们也一直这样做,所以我们貌似生活在一片遵循了OCP的美好景象之下,但事实是什么样呢?

    作为考察,我打开了当初我自己写的一个类com.xxx.xxx.szx.domain.service.booking.impl.MobileChargingServiceImpl,这个类最初的职责是完成手机充值后的处理逻辑,包括:

1、   更新手机已充金额和充值状态

2、   如果批次手机充值完毕,对无法完成充值的手机充值申请进行退款

3、   如果批次手机充值完毕,向充值申请人发送充值完成的信息。

当然,这些职责并不是直接由MobileChargingServiceImpl类来完成,而是分别抽象到三个不同的接口中完成的。我今天查了一下这个类在SVN上的修改记录,截图如下:



    即使排除了因为Bug而做的修改,我们是否遵循OCP已经不言而喻了。从这一坨修改记录中,我挑了Revision 81623看了看,这应该是一个后来添加的需求,即:"对易趣商户的手机充值订单,充值完成后要调用该商户的回调接口。" 这显然是一颗新子弹,很不幸我们被击中了。于是我看到这个类中多了一段这样的代码:
//是否易趣订单,调用易趣回调通知
    LOG.info("##########################################------------------------yiqu order charge comlate"+orderId);
    if(eqHandleResponseService.isEqOrder(order.getOrderId())){
        LOG.info("------------eq order handle process ------------"+orderId);
        eqHandleResponseService.notifyEqProcess(order);    }


    单独为易趣写一个EqHandleResponseService这样的方式是否合适我们这次不探讨,显然上面的代码并没有尝试去隔离变化,如果将来淘宝也要求发送回调通知,那我们还要修改MobileChargingServiceImpl类,如此反复。那么怎么隔离这种变化呢?我觉得可以这样:



    通过添加一个MerchantCallback接口,商户通知方面的变化就被隔离在MobileChargingServiceImpl之外了,OCP原则也就被遵循了。

    这里我无意指责我们的开发人员,我们的设计能力有限,这正说明我们有提高的空间。要提高就需要看到我们的问题所在,遵循正确的原则去解决这些问题。

    Bob叔叔在一篇"软件之美"的文章中说:"除了我的家庭,软件是我的挚爱。通过它,我可以创造出美的东西。软件之美在于它的功能,在于它的内部结构,还在于团队创建它的过程。"我们离欣赏软件之美还有比较远的距离,但是按照前人证明过的方法和原则来构建我们系统的过程,跟我们的team一起优化和重构我们系统的过程,一样有值得享受的东西。
  • 大小: 79.6 KB
  • 大小: 12.7 KB
分享到:
评论

相关推荐

    软件设计的七大原则(OOD)

    OCP是软件设计的七大原则之一,它的定义是:软件实体(类、模块、函数/方法等等)对于扩展应该是开放的,对于修改应该是封闭的。OCP可以提高软件模块的可重用性和可维护性,软件产品具有良好的稳定性和持久性。OCP的...

    如何解释OOD及设计

    在这一阶段,应该遵循面向对象的原则,如单一职责原则、开放封闭原则等,以确保代码的质量。 7. **测试与迭代**:对软件进行测试,验证其功能和性能是否符合预期。根据测试结果进行必要的调整和优化。 8. **文档...

    PHP面向对象五大原则之开放-封闭原则(OCP)详解

    开放-封闭原则(Open-Closed Principle,OCP)是面向对象设计(OOD)的五大原则之一,由Bertrand Meyer在1998年提出。该原则旨在指导软件系统的设计,使其能够容易地扩展新功能,同时在扩展时不影响现有代码的稳定性...

    Uncle Bob OOD Principles

    2. **开放封闭原则(Open-Closed Principle, OCP)**:类应该是对扩展开放的,对修改封闭的。当需要增加新功能时,我们应该通过扩展已有类的行为,而不是直接修改它们的源代码。这可以通过继承、接口或策略模式等...

    面向对象设计的SOLID原则 .docx

    SOLID 原则是面向对象设计和编程(OOD&OOP)中几个重要编码原则的首字母缩写,分别是单一责任原则、开放封闭原则、里氏替换原则、依赖倒置原则和接口分离原则。这些原则是非常基础而且重要的面向对象设计原则,理解...

    OOA、OOD和UML

    4. **设计原则**:如单一职责原则、开放封闭原则、里氏替换原则、依赖倒置原则等,它们指导良好的设计实践。 5. **设计模式**:如工厂模式、单例模式、观察者模式等,它们是解决常见设计问题的通用解决方案。 6. **...

    面向对象设计的基本原则

    2. **开放封闭原则 (Open-Closed Principle, OCP)** - 一个软件实体(如类、模块或函数)应该是对扩展开放的,但对修改关闭的。这意味着可以在不修改原有代码的情况下增加新功能,通过继承或接口实现扩展。 3. **...

    讲述了面向对象设计的原则

    开放封闭原则指出软件实体(如类、模块等)应该是可以扩展但不可修改的。当需要增加新功能时,可以通过添加新的代码来实现,而不是修改现有的代码。这有助于降低系统各部分之间的耦合度,减少因修改现有代码而引入新...

    面向对象的设计原则详解

    8. 共同封闭原则(Common Closure Principle, CCP): 包内的所有类应对相同类型的变化具有共同的封闭性,即一个变更影响到包内的所有类。这有助于维护,因为所有相关的改动可以集中在一个地方进行。 9. 无环依赖...

    面向对象设计的基本原则和实践建议

    2. **开放封闭原则(Open-Closed Principle, OCP)**:软件实体(类、模块、函数等)应对于扩展开放,对于修改封闭。这意味着在不改动原有代码的情况下,可以通过扩展增加新功能。实现这一原则的关键是抽象和多态。 ...

    61条面向对象设计的经验原则

    2. **开放封闭原则(Open-Closed Principle, OCP)**:软件实体(如类、模块或函数)应当对扩展开放,对修改封闭。这意味着在不改动原有代码的情况下,可以通过增加新代码来扩展功能。 3. **里氏替换原则(Liskov ...

    面向对象设计原则:突破软件工程学习的质的飞跃

    开放-封闭原则强调软件实体应该是可扩展的,但不可被修改。这一原则的核心在于通过抽象来管理变化,使软件系统能够在不修改现有代码的情况下适应新的需求。为了实现这一目标,可以通过以下几种方式: - **抽象化**...

    OO Design Principles & Metrics

    开放封闭原则指出,软件实体(如类、模块等)应当对扩展开放,对修改封闭。这意味着可以在不修改现有代码的基础上增加新的功能,保持软件的稳定性。 #### 单一职责原则 单一职责原则强调一个类应该只有一个引起它...

    Object Oriented Design in Java

    2. **设计原则**:OOD强调设计原则,如单一职责原则(SRP)、开放封闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)和依赖倒置原则(DIP)。这些原则指导开发者创建可维护、可扩展的代码结构。 3. **设计...

    深入浅出面向对象分析与设计.pdf

    3. **编码实现**:按照设计文档编写代码,注意遵循面向对象设计的原则,如单一职责原则、开放封闭原则等。 4. **测试与维护**:完成编码后进行测试,确保系统满足需求。在后期维护过程中,也要遵循面向对象设计的...

    61条面向对象设计的经验面试题

    2. **开放封闭原则(Open-Closed Principle, OCP)**:软件实体(类、模块、函数等)应对于扩展开放,对于修改关闭。这意味着可以通过增加新代码而非修改现有代码来实现功能扩展。 3. **里氏替换原则(Liskov ...

    System-Design:与系统设计和面向对象设计(OOD)相关的面试问题和解决方案

    2. **SOLID原则**:这是面向对象设计的五项基本原则,包括单一职责原则、开放封闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。 3. **类与对象的关系**:了解如何定义类、对象以及它们之间的关系,如继承、...

Global site tag (gtag.js) - Google Analytics