1、英文定義:
Software entities like classes,modules and functions should be open for extension but closed for modifications.
一個(gè)軟件實(shí)體如類,模塊和函數(shù)應(yīng)該對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉
舉個(gè)列子:

如圖:有一個(gè)汽車服務(wù)中心,為路過(guò)的汽車提供補(bǔ)給,有一Car類,代表過(guò)往的汽車定義了一個(gè)refuel(加油)方法,服務(wù)類調(diào)用refuel為車加油。
代碼如下:
/**
* 汽車類
* @author saisaimayi
*
*/
public class Car {
private String name;
public Car(String name){
this.name = name;
}
public void refuel(){
System.out.println("refuel for "+name+" car...");
}
}
/**
* 汽車服務(wù)中心
* @author saisaimayi
*
*/
public class CarServiceCenter {
private List<Car> cars = new ArrayList<Car>();
public void addCar(Car car){
cars.add(car);
}
public void service(){
System.out.println("service for cars...");
for (Car car : cars) {
car.refuel();
}
}
}
public class Client extends TestCase {
public void test(){
CarServiceCenter center = new CarServiceCenter();
center.addCar(new Car("volkswagan"));
center.addCar(new Car("benz"));
center.service();
}
}
這個(gè)時(shí)候如果需要添加另外一種新能源的車,不需要加油,而是需要充電(charge)。
這個(gè)時(shí)候需要怎么設(shè)計(jì)? 一般有以下兩種設(shè)計(jì)方法:
1、在類Car中新增一個(gè)charge方法,判斷如果是新能源汽車,就充電,很顯然,這不是一種好的設(shè)計(jì),意味著要改變?cè)械拇a,給原本穩(wěn)定的功能帶來(lái)的新的風(fēng)險(xiǎn)。
2、修改設(shè)計(jì),把Car抽象為接口,各種車實(shí)現(xiàn)該接口。
修改后的結(jié)構(gòu)如下:

將Car抽象為接口,其它各種車實(shí)現(xiàn)該接口,實(shí)現(xiàn)refeul方法.新能源汽車的refuel方法,調(diào)用自身的charge方法實(shí)現(xiàn)充電。
代碼如下:
/**
* 車接口
* @author saisaimayi
*
*/
public interface ICar {
public void refuel();
}
/**
* 普通車
* @author saisaimayi
*
*/
/**
* 普通車
* @author saisaimayi
*
*/
public class NormalCar implements ICar {
private String name;
public NormalCar(String name){
this.name = name;
}
public void refuel() {
System.out.println("refuel for normalcar "+name+"...");
}
}
/**
* 電動(dòng)車
* @author saisaimayi
*
*/
public class ElectricCar implements ICar {
private String name;
public ElectricCar(String name){
this.name = name;
}
public void refuel() {
System.out.println("need charge for electric car..");
charge();
}
private void charge() {
System.out.println("charge for electric car "+name+"..");
}
}
/**
* 測(cè)試類
* @author saisaimayi
*
*/
/**
* 測(cè)試類
* @author saisaimayi
*
*/
public class Client extends TestCase {
public void test(){
CarServiceCenter center = new CarServiceCenter();
ICar volkswagan = new NormalCar("volkswagan");
ICar benz = new ElectricCar("benz");
center.addCar(volkswagan);
center.addCar(benz);
center.service();
}
}
service for cars...
refuel for normalcar volkswagan...
need charge for electric car..
charge for electric car benz..
使用開閉原則的理由:
1、由于對(duì)修改關(guān)閉,可以保證有新增功能時(shí),原有代碼的安全性。減少對(duì)原有功能回歸測(cè)試耗費(fèi)的時(shí)間和風(fēng)險(xiǎn)。
2、縮小代碼的邏輯粒度,增強(qiáng)可復(fù)用性。代碼可復(fù)用的概率是由代碼的粒度決定的,一般來(lái)說(shuō),代碼的邏輯粒度越小,越容易被復(fù)用。一個(gè)功能復(fù)雜的類,復(fù)用起來(lái)可能會(huì)帶來(lái)很多不便,但是如果拆分成多個(gè)小模塊,可復(fù)用的概率就提高了。開閉原則讓擴(kuò)展和原來(lái)的接口分離,實(shí)現(xiàn)了邏輯的拆分。
3、提高可靠性和可維護(hù)性。維護(hù)人員修改代碼只需關(guān)注自己擴(kuò)展的部分,可以盡量避免歷史代碼帶來(lái)的束縛與不確定的風(fēng)險(xiǎn)。