原文链接:Open Close Principle
Motivation
动机
A clever application design and the code writing part should take care of the frequent changes that are done during the development and the maintaining phase of an application. Usually, many changes are involved when a new functionality is added to an application. Those changes in the existing code should be minimized, since it's assumed that the existing code is already unit tested and changes in already written code might affect the existing functionality in an unwanted manner.
一个聪明的应用程序设计和代码编写部分应该处理在应用程序的开发和维护阶段中进行的频繁更改。 通常,在将新功能添加到应用程序时会涉及许多更改。 现有代码中的这些更改应该最小化,因为假设现有代码已经过单元测试,并且已编写代码的更改可能会以不需要的方式影响现有功能。
The Open Close Principle states that the design and writing of the code should be done in a way that new functionality should be added with minimum changes in the existing code. The design should be done in a way to allow the adding of new functionality as new classes, keeping as much as possible existing code unchanged.
开放式关闭原则指出,代码的设计和编写应该以一种方式完成,即应该在现有代码中进行最少的更改来添加新功能。 设计应该以允许添加新功能作为新类的方式完成,尽可能保持现有代码不变。
Intent
意图
Software entities like classes, modules and functions should be open for extension but closed for modifications.
类,模块和函数等软件实体应该是可以扩展的,但是对于修改是封闭的。
Example
例子
Bellow is an example which violates the Open Close Principle. It implements a graphic editor which handles the drawing of different shapes. It's obviously that it does not follow the Open Close Principle since the GraphicEditor class has to be modified for every new shape class that has to be added. There are several disadvantages:
下面是违反开放闭合原则的一个例子。 它实现了一个图形编辑器,可以处理不同形状的绘制。 显然它不遵循开放闭合原则,因为必须为每个必须添加的新形状类修改GraphicEditor类。 有几个缺点:
for each new shape added the unit testing of the GraphicEditor should be redone.
when a new type of shape is added the time for adding it will be high since the developer who add it should understand the logic of the GraphicEditor.
adding a new shape might affect the existing functionality in an undesired way, even if the new shape works perfectly
对于每个添加的新形状,应重新绘制GraphicEditor的单元测试。
当添加新类型的形状时,添加它的时间会很高,因为添加它的开发人员应该理解GraphicEditor的逻辑。
添加新形状可能会以不希望的方式影响现有功能,即使新形状完美运行也是如此。
In order to have more dramatic effect, just imagine that the Graphic Editor is a big class, with a lot of functionality inside, written and changed by many developers, while the shape might be a class implemented only by one developer. In this case it would be great improvement to allow the adding of a new shape without changing the GraphicEditor class.
为了获得更具戏剧性的效果,想象一下,图形编辑器是一个很大的类,内部有许多功能,许多开发人员编写和更改,而形状可能只是由一个开发人员实现的类。 在这种情况下,允许添加新形状而不更改GraphicEditor类将是一个很大的改进。
// Open-Close Principle - Bad example
class GraphicEditor {
public void drawShape(Shape s) {
if (s.m_type==1)
drawRectangle(s);
else if (s.m_type==2)
drawCircle(s);
}
public void drawCircle(Circle r) {....}
public void drawRectangle(Rectangle r) {....}
}
class Shape {
int m_type;
}
class Rectangle extends Shape {
Rectangle() {
super.m_type=1;
}
}
class Circle extends Shape {
Circle() {
super.m_type=2;
}
}
Bellow is a example which supports the Open Close Principle. In the new design we use abstract draw() method in GraphicEditor for drawing objects, while moving the implementation in the concrete shape objects. Using the Open Close Principle the problems from the previous design are avoided, because GraphicEditor is not changed when a new shape class is added:
下面是支持开放闭合原则的一个例子。 在新设计中,我们在GraphicEditor中使用抽象draw()方法绘制对象,同时在具体形状对象中移动实现。 使用Open Close Principle可以避免以前设计中出现的问题,因为添加新的shape类时不会更改GraphicEditor:
no unit testing required.
no need to understand the sourcecode from GraphicEditor.
since the drawing code is moved to the concrete shape classes, it's a reduced risk to affect old functionallity when new functionallity is added.
无需单元测试。
无需了解GraphicEditor的源代码。
由于绘图代码被移动到具体的形状类,因此当添加新的功能时,降低影响旧功能的风险。
// Open-Close Principle - Good example
class GraphicEditor {
public void drawShape(Shape s) {
s.draw();
}
}
class Shape {
abstract void draw();
}
class Rectangle extends Shape {
public void draw() {
// draw the rectangle
}
}
Conclusion
总结
Like every principle OCP is only a principle. Making a flexible design involves additional time and effort spent for it and it introduce new level of abstraction increasing the complexity of the code. So this principle should be applied in those area which are most likely to be changed.
There are many design patterns that help us to extend code without changing it. For instance the Decorator pattern help us to follow Open Close principle. Also the Factory Method or the Observer pattern might be used to design an application easy to change with minimum changes in the existing code.
像每个原则一样,OCP只是一个原则。 进行灵活的设计需要花费额外的时间和精力,并引入新的抽象级别,增加了代码的复杂性。 因此,这一原则应适用于最有可能改变的领域。
有许多设计模式可以帮助我们在不改变代码的情况下扩展代码。 例如,装饰模式帮助我们遵循开放式关闭原则。 此外,工厂方法或观察者模式可用于设计易于更改的应用程序使现有代码中的更改最少。