●定义

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

“开放-封闭”原则(The open-Closed Principle)可以说是面向对象设计的核心所在。

“开放-封闭”原则的两个重要特点是“对扩展开放,对修改关闭”,即允许对程序作出扩展(以扩展的方式响应需求的变化),但拒绝对程序作出修改(即修改之前运行良好的程序)。

实现“开放-封闭”原则的重要机制就是“抽象”与“多态”。通过对“变化”进行抽象隔离,使程序具有更好的扩展性与可维护性。

●以具体的代码演示OCP

没有遵循OCP原则的示例

客户将要使用的电脑(方正)

public class FangZhengComputer
{
public FangZhengComputer()
{
    //...构造函数
}

public string OutCpuInfo()
{
    return "fangzheng's Cpu!" ;
}
//...other Method
}

客户使用电脑(客户代码)

FangZhengComputer  myComputer = new FangZhengComputer() ;
myComputer.OutCpuInfo() ;

上面代码中客户使用的是方正电脑。现在,客户要使用联想电脑(需求变化),那我们的程序应该怎么变化?很明显,我们可能会增加一种电脑类型(有人也许会直接将方正电脑改变联想电脑),然后去更改客户端的代码。这样做带来的后果在某些情况下是很难让人接受的。

遵循OCP原则的示例

上面的代码其弊端在于:客户端直接依赖于一个具体的实现,当具体实现发生变化时,客户端代码也要发生变化。现在,我们将“变化”的部分(即 new FangZhengComputer() ;)进行抽象隔离。

首先定义一个抽象类,它是客户使用电脑的基类

public abstract class Computer
{
   public abstract string OutCpuInfo();
   //other Method
}

然后定义一个联想电脑类,它从Computer类继承

public class LianXiangComputer : Computer
{
   public override string OutCpuInfo()
   {
    return "LianXiangComputer's Cpu!" ;
   }
   //other Method
}

客户端调用:

Computer myComputer = new Computer () ;

这时,客户端依赖就不是一个具体的实现了,它依赖的是一个抽象,所以当Computer类的某个子类发生变化时,客户端代码是不需要发生变化的。这样,如果客户今天又要使用宏基电脑,那只需要从Computer 类继承一个子类就可以了,这就是扩展,同时,之前的代码(包括客户端的和已经存在的电脑类型)都不需要发生变化。

(我们上面的代码不是很完全,可以利用工厂加上配置文件来动态指定所要使用的电脑类型)