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:具有前瞻性的设计类结构,而不是盲目在于实现,抽象的好,自然就可以直接派生了】