一、定义

  软件实体(类、模块、函数等)应该是可以扩展的,但是不可修改。

  如果正确的应用了OCP原则,那么 以后在进行同样的改动时,就只需要添加新的代码,不必修改已经正常运行的代码。

二、OCP概述

  1.对于扩展是开放的

  这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。换句话说,我们可以改变模块的功能。

  2.对于修改是封闭的

  对模块进行扩展时,不必改动模块的源代码或者二进制代码。

  3.有何问题

  这两个特征好像是互相矛盾的。扩展模块行为的通常方式就是修改该模块的源代码。不允许修改模块常常都认为具有固定的行为。

  4.如何实现?(抽象)

  怎么可能在不改动源代码的情况下去更改它的行为呢?如果不更改一个模块,又怎么能够去改变它的功能呢?

  答案是抽象。在C#中,可以创建出固定却能够描述一组任意个可能行为的抽象体。这个抽象体就是抽象基类。而这一组任意个可能的行为则表现为可能的派生类。

  模块可能对抽象体进行操作。由于模块依赖于一个固定的抽象体,所以它对于更改可以是封闭的。同时,通过从这个抽象体派生,可以扩展此模块的行为。

  下图展示了一个简单的不遵循OCP的设计。Client类和Server类都是具体类。Client类使用Server类,如果我们希望Client对象使用另一个不同的服务器对象,那么就必须要把Client类中使用Server类的地方更改为新的服务器类。

  OCP开放封闭原则-LMLPHP 

  下图则使用Strategy模式(策略模式)展示了一个针对上述问题的遵循OCP的设计。

  OCP开放封闭原则-LMLPHP

  下图展示了另一个使用Template method模式(模版方法模式)的结构。

  OCP开放封闭原则-LMLPHP

  和图2中Client类的函数类似,Policy类具有一组实现了某个策略的具体公共函数。和前面一样,这些策略函数根据一些抽象接口描绘了要完成的功能,不同的是,在这个结构中,这些抽象接口是Policy类本身的一部分。在C#中,它们是抽象方法。这些函数在Policy类子类型中实现。这样,可以通过从policy类派生出新类的方式,对Policy中指定的行为进行扩展。

三、结论

  在很多方面,OCP都是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处:灵活性、可重用性以及可维护性。

  拒绝不成熟的抽象和抽象本身一样重要。

04-17 05:12