开放/封闭原则规定软件实体(类,模块等)应该是可以扩展的,但是对于修改是封闭的.这意味着什么,为什么它是良好的面向对象设计的重要原则?
这意味着您应该将新代码放入新的类/模块中.应仅修改现有代码以修复错误.新类可以通过继承重用现有代码.
开放/封闭原则旨在降低引入新功能时的风险.由于您不修改现有代码,因此可以确保它不会被破坏.它降低了维护成本并提高了产品稳定性.
具体来说,它是关于OOP中设计的"圣杯",即使实体可扩展(通过其个人设计或通过其参与架构)来支持未来不可更改的更改而无需重写其代码(有时甚至无需重新编译**).
一些方法包括多态性/继承,组合,控制反转(又名DIP),面向方面编程,模式,如策略,访问者,模板方法,以及OOAD的许多其他原则,模式和技术.
**参见6"包原则",REP,CCP,CRP,ADP,SDP,SAP
这是脆弱的基类问题的答案,它说对基类的看似无辜的修改可能会对依赖于先前行为的继承者产生意想不到的后果.因此,您必须小心地封装您不想依赖的内容,以便派生类将遵循基类定义的契约.一旦存在继承者,你必须非常小心你在基类中改变了什么.
比DaveK更具体地说,通常意味着如果要添加其他功能或更改类的功能,请创建子类而不是更改原始类.这样,任何使用父类的人都不必担心以后会改变它.基本上,它都是关于向后兼容性的.
面向对象设计的另一个非常重要的原则是通过方法接口的松散耦合.如果您要进行的更改不会影响现有界面,则更改非常安全.例如,使算法更有效.面向对象的原则也需要通过常识来缓和:)
软件实体应开放以进行扩展,但应封闭以进行修改
这意味着任何类或模块都应以可以原样使用,可以扩展但必须修改的方式编写
var juiceTypes = ['Mango','Apple','Lemon']; function juiceMaker(type){ if(juiceTypes.indexOf(type)!=-1) console.log('Here is your juice, Have a nice day'); else console.log('sorry, Error happned'); } exports.makeJuice = juiceMaker;
现在,如果要添加其他果汁类型,则必须编辑模块本身。这样,我们就打破了OCP。
var juiceTypes = []; function juiceMaker(type){ if(juiceTypes.indexOf(type)!=-1) console.log('Here is your juice, Have a nice day'); else console.log('sorry, Error happned'); } function addType(typeName){ if(juiceTypes.indexOf(typeName)==-1) juiceTypes.push(typeName); } function removeType(typeName){ let index = juiceTypes.indexOf(typeName) if(index!==-1) juiceTypes.splice(index,1); } exports.makeJuice = juiceMaker; exports.addType = addType; exports.removeType = removeType;
现在,您可以从模块外部添加新的果汁类型,而无需编辑同一模块。