OCP(The Open-Close Principle, 开放-封闭原则)
软件实体(类、模块、函数等)应该是可扩展的,但是不可修改的特征:
对于扩展是开放的(Open for extension)
模块的行为可以扩展,当应用的需求改变时,可以对模块进行扩展,以满足新的需求
对于更改是封闭的(Closed for modification)
对模块行为扩展时,不必改动模块的源代码或二进制代码
OCP的关键在于抽象
OCP的关键在于抽象
抽象技术:abstract class, Interface
抽象预见了可能的所有扩展(闭) 【PS:抽象出不变的】
由抽象可以随时导出新的类(开) 【PS: 变化的交给子类】
范例:手与门
如何在程序中模拟用手去开门和关门?
行为:
开门(open)
关门(close)
判断门的状态(isOpened)
设计与实现
public class Door {
private boolean _isOpen=false;
public boolean isOpen(){
return _isOpen;
}
public void open(){
_isOpen = true;
}
public void close(){
_isOpen = false;
}
}
public class Hand {
public Door door;
void do() {
if (door.isOpen())
door.close();
else
door.open();
}
}
public class SmartTest {
public static void main(String[] args) {
Hand myHand = new Hand();
myHand.door = new Door();
myHand.do();
}
}
虽然实现了,但是如果有新的需求我们要改写代码
新的需求……
需要手去开关抽屉,冰箱……?
我们只好去修改程序!
public class Hand {
public Door door;
public Drawer drawer;
void do(int item) {
switch (item){
case 1:
if (door.isOpen())
door.close();
else door.open();
break;
case 2:
if (drawer.isOpen())
drawer.close();
else drawer.open();
break;
}
}
}
符合OCP的设计方案
public interface Excutable {
public boolean isOpen();
public void open();
public void close();
}
public class Door implements Excutable {
private boolean _isOpen = false;
public boolean isOpen() {
return _isOpen;
}
public void open() {
_isOpen = true;
}
public void close() {
_isOpen = false;
}
}
public class Drawer implements Excutable {
private boolean _isOpen = false;
public boolean isOpen() {
return _isOpen;
}
public void open() {
_isOpen = true;
}
public void close() {
_isOpen = false;
}
}
public class Hand {
public Excutable item;
void do() {
if (item.isOpen())
item.close();
else
item.open();
}
}
其实笔者认为,开闭原则无非就是想表达这样一层意思:用抽象构建框架,用实现扩展细节。因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节,我们用从抽象派生的实现类来进行扩展,当软件需要发生变化时,我们只需要根据需求重新派生一个实现类来扩展就可以了。当然前提是我们的抽象要合理,要对需求的变更有前瞻性和预见性才行。【PS:具有前瞻性的设计类结构,而不是盲目在于实现,抽象的好,自然就可以直接派生了】