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

开闭原则 思考(转)

阅读更多

开闭原则的定义

Software entities should be open for extension, but closed for modification.

软件实体应该对扩展是开放的,但是对于修改应当是关闭的.凡是定义一般都是很晦涩的,那么下面举一个应用场景来说明开闭原则的价值.

 

第一天,客户提出一个需求,我们需要将用户对象存储到文件的UserDAO.

解决方案:

 

Java代码 复制代码
  1. public class UserDAO{   
  2.        
  3.     public void saveUser(User user)   
  4.     {   
  5.         //将一个用户对象存储到文件.   
  6.     }   
  7. }   
public class UserDAO{
	
	public void saveUser(User user)
	{
		//将一个用户对象存储到文件.
	}
} 

 

半个月后,客户有了新的需求,它们需要将一部分用户对象存储到XML文件.

方案1(破坏OCP原则):

Java代码 复制代码
  1. public class UserDAO {   
  2.   
  3.     public void saveUser(User user, String saveMethod) {   
  4.         if (saveMethod.equals("txt")) {   
  5.             // 将一个用户对象存储到文本文件.   
  6.         } else if (saveMethod.equals("xml")) {   
  7.             // 将一个用户对象存储到xml文件.   
  8.         }   
  9.     }   
  10. }  
public class UserDAO {

	public void saveUser(User user, String saveMethod) {
		if (saveMethod.equals("txt")) {
			// 将一个用户对象存储到文本文件.
		} else if (saveMethod.equals("xml")) {
			// 将一个用户对象存储到xml文件.
		}
	}
}

这个方案带来的变化:

1.我要修改依赖UserDAO的类,让其多传入一个参数saveMethod

2.我要维护if...else判断的正确性,如果传入的字符不是txt和xml,那么我还要进行异常处理.

3.加入存储到xml的代码后我无法预知对原来存储到txt的功能是否造成了影响.

4.如果需求再一次变化,那么我必须继续修改saveUser方法,甚至可能因为需要更多的参数而修改了依赖UserDAO的类.

 

方案2(遵循OCP原则):

Java代码 复制代码
  1. public interface IUserDAO {   
  2.   
  3.     public void saveUser(User user);   
  4. }   
  5.   
  6. public class UserDAOTXTImp implements IUserDAO   
  7. {   
  8.     public void saveUser(User user)   
  9.     {   
  10.         //存储到txt   
  11.     }   
  12. }   
  13.   
  14. public class UserDAOXMLImp implements IUserDAO   
  15. {   
  16.     public void saveUser(User user)   
  17.     {   
  18.         //存储到xml   
  19.     }   
  20. }  
public interface IUserDAO {

	public void saveUser(User user);
}

public class UserDAOTXTImp implements IUserDAO
{
	public void saveUser(User user)
	{
		//存储到txt
	}
}

public class UserDAOXMLImp implements IUserDAO
{
	public void saveUser(User user)
	{
		//存储到xml
	}
}

这个方案带来的变化:

1.我要修改依赖UserDAO的类,让其依赖IUserDAO接口.

2.我重新实现一个存储到xml的UserDAO.

3.即使需求发生变化,需要存储到数据库的,我只需要重新实现IUserDAO接口.

4.这样的修改不会破坏原有程序.

 

以上看来是一个标准的OCP原则教程,那么下面我们进行进一步的思考:

 

来看看我们破坏了几次OCP原则.

第一天的开发,没有破坏OCP原则,我们只是单纯的增加了一个新功能.

半个月后的开发,无论我们采用方案一还是方案二我们都破坏了OCP原则.

如果我们使用方案一,在以后的变化中我们就会继续破坏OCP原则,并且带来很多负面的影响.

 

如果我在第一天就采用IUserDAO,整个过程都不会破坏OCP原则,听起来很不错.

那么我来对比一下第一天就采用IUserDAO所带来的不同:

 

IUserDAO方案:

1.我要做更多的工作,如果以后没有两种以上的实现,这个接口将毫无意义.

2.如果接口不稳定,比如要增加一个读取用户的操作,那么我们必须修改IUserDAO与UserDAO两个地方,增加了额外的工作量.

3.增加了程序的复杂度.

这个方案如果以后没有需求变化,将给系统带来无用的设计以及更多的维护成本.

 

UserDAO方案:

1.即使有了需求变化,要抽取出一个借口也是非常方便的,相对于IUserDAO方案并没有多出太多的工作量.

2.使用UserDAO方案破坏了OCP原则,破坏了DIP原则,没有依赖于抽象而依赖于具体实现.但是,我们一定要遵循这些原则吗?

3.程序简单直接,易维护.

 

我无法预期半个月后的那次需求变动,因此我不应该做提前的设计.

 

我对OpenClose原则的解释:

你对一类问题需要 一个以上的解决方案, 那么当加入新的解决方案时,你的修改不应该对已有模块产生影响,而你可以通过对抽象的实现来进行扩展.

OpenClose原则对于此外的场景是无意义的,比如你要加入一个新功能,IUserDAO现在需要读取用户的方法,你肯定要打开IUserDAO进行修改,这个时候破坏OpenClose原则是必然的.

分享到:
评论

相关推荐

    该怎么使用Java设计模式编程中的OCP开闭原则?.pdf

    然而,通过仔细思考和阅读许多设计模式的文章后,我们终于对开闭原则有了一点认识。其实,我们遵循设计模式前面五大原则,以及使用 23 种设计模式的目的就是遵循开闭原则。 要遵循开闭原则,我们需要对系统进行抽象...

    python开闭原则.docx

    **开闭原则** 是面向对象设计的一个核心原则,它的主要思想是软件实体(如类、模块、函数等...在设计系统时,我们应该始终思考如何在不破坏现有代码结构的前提下,增加新功能或改进现有功能,以体现出开闭原则的精神。

    设计模式之开放封闭原则

    **正文** 设计模式是软件开发中的重要概念,它是一种在特定场景下解决常见问题的经验总结,为代码设计提供了...在进行代码设计时,始终思考如何通过增加新代码而不是修改旧代码来应对需求变更,是实践OCP的关键所在。

    设计模式——6大软件设计原则(demo案例实现,附带解析,快速掌握软件设计原则的精髓)

    1、开闭原则 2、里氏代换原则 3、依赖倒转原则 4、接口隔离原则 5、迪米特法则 6、合成复用原则 使用了一个个的demo案例,以通俗易懂的生活案例解析软件开发设计原则,掌握开发细节。写出耦合度低、易于扩展...

    Java面向对象设计原则.docx

    原则3: 开闭原则 Open-Close Principle(OCP) 即对扩展开放,对修改关闭。这是另一种非常棒的设计原则,可以防止其他人更改已经测试好的代码。理论上,可以在不修改原有的模块的基础上,扩展功能。这也是开闭原则的...

    16丨理论二:如何做到“对扩展开放、修改关闭”?扩展和修改各指什么?1

    开闭原则的应用需要我们深入思考系统的结构和扩展需求,利用抽象和多态等面向对象特性来设计代码。在实际项目中,我们可以结合其他设计模式,如策略模式、装饰者模式等,来更好地实现开闭原则。通过这样的设计,我们...

    软件设计原则

    7. 开闭原则(Open/Closed Principle) 你所编写的软件实体(类、模块、函数等)最好是开放的,这样别人可以拓展开发。不过对于你的代码,得限定别人不得修改。 8. 代码维护(Write Code for the Maintainer) 一...

    02-软件设计原则 模式深度解析和案例分析

    设计原则通常包括但不限于单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)以及依赖倒置原则(DIP)等。 - **单一职责原则** (SRP): 指一个模块或类应该只负责一项功能的变化,即一个类或...

    敏捷软件开发+原则、模式与实践.pdf

    例如,他强调面向对象设计的重要性,提倡使用设计原则,如单一职责、开闭原则、依赖倒置原则等,以提高软件设计的质量。 此外,书中还包含了大量可复用的C++和Java源代码示例。这些代码示例不仅展示了如何实现特定...

    8接口分离原则-课程内容.rar

    8. **设计原则的结合**:ISP与其他SOLID原则如单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)和依赖倒置原则(DIP)共同作用,构建出高质量、可扩展的软件架构。 9. **实践建议**:在实际开发中,要...

    用设计模式思考 Thinking in Patterns

    这些模式共同构成了软件设计的基石,帮助开发者遵循“开闭原则”,即对扩展开放,对修改关闭,提高代码的灵活性和可维护性。 在实际编程中,理解并熟练运用设计模式可以显著提升代码质量,减少代码的冗余,提高团队...

    软件工程--实践者的思考 (Roger.S Pressman)

    3. **设计模式与架构**:Pressman详细阐述了软件设计的原则和模式,如单一职责原则、开闭原则等,以及如何构建模块化、可扩展的系统架构。设计模式如工厂模式、观察者模式等,是软件设计中常用的最佳实践。 4. **...

    高级软件工程之设计模式.ppt

    文档中提到了一个关于长方形和正方形的案例,这是对设计模式中的“开闭原则”(Open-Closed Principle)和“里氏替换原则”(Liskov Substitution Principle)的一个经典讨论。 首先,让我们回顾一下案例。我们有一...

    考试类精品--「JavaGuideInterview学习」每日 3+1,以面试题来驱动学习,提倡每日学习与思考,每天.zip

    2. **面向对象编程**:深入理解面向对象的设计原则,如单一职责原则、开闭原则、里氏替换原则、依赖倒置原则和接口隔离原则。此外,了解如何设计良好的类和接口,以及如何利用抽象、继承和多态来构建可扩展的系统。 ...

    面向对象技术扩充读物

    在面向对象设计(OOAD)中,这一理念意味着我们应该持续反思设计决策,确保我们的类和对象设计能够适应需求变化,符合开闭原则(对扩展开放,对修改关闭),并遵循SOLID原则。 提供的文件中,"a1972-dijkstra.pdf...

    详解Java设计模式编程中的依赖倒置原则

    4. 有利于实现开闭原则:系统对扩展开放,对修改关闭,即在不修改原有代码的基础上,可以方便地添加新的功能。 在实践中,为了遵循依赖倒置原则,我们可以: 1. 尽可能地定义接口或抽象类,作为模块之间的交互点。...

    java应用设计实用素材(专业)

    - **Principle原则.doc** 和 **软件设计的七大原则.doc** 强调了软件设计的基本原则,例如开闭原则(对扩展开放,对修改关闭)、依赖倒置原则、里氏替换原则等。这些原则指导我们编写可维护、可扩展的代码。 3. **...

Global site tag (gtag.js) - Google Analytics