Open Close Principle - 开放式关闭原则

原文链接: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类将是一个很大的改进。

ocp.bad.gif
// 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的源代码。

  • 由于绘图代码被移动到具体的形状类,因此当添加新的功能时,降低影响旧功能的风险。

ocp.good.gif
// 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只是一个原则。 进行灵活的设计需要花费额外的时间和精力,并引入新的抽象级别,增加了代码的复杂性。 因此,这一原则应适用于最有可能改变的领域。

有许多设计模式可以帮助我们在不改变代码的情况下扩展代码。 例如,装饰模式帮助我们遵循开放式关闭原则。 此外,工厂方法或观察者模式可用于设计易于更改的应用程序使现有代码中的更改最少。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,322评论 0 10
  • 范七 2Jae Chapter17:第二期PIA戏(中) 接着便是向日葵和孤儿怨的对手戏了。 孤儿怨:“上官小姐,...
    亦木辛阅读 232评论 0 1
  • 大家好,这里是夜雨情感故事。每天一个小故事,给大家带来欢乐。今天给大家要说的是公交车上面的爆笑故事。 出门乘坐公交...
    啸夜雨阅读 939评论 1 0
  • 数学特级教师吴正宪:“我愿意!”有营养又好吃的数学教育,让儿童更喜欢,坚持站在儿童的立场,儿童的视角,让课堂更温暖...
    刘杰平ljp阅读 164评论 0 0
  • 2015.07.26 00:04 我的上一篇简书被我直接发给了他,真的要剁手好吗,真的不是要发给他的。我已经无法...
    阿雨的大天地阅读 184评论 0 1