寂然解读设计模式 - 开闭原则

I walk very slowly, but I never walk backwards 

设计模式原则 - 开闭原则


寂然

大家好,我是寂然~,本节课呢,我来给大家介绍设计模式原则之开闭原则,话不多说,我们直接进入正题,老规矩,首先带大家了解一下开闭原则的官方定义,并作一个解释,然后我们通过案例代码来具体分析

官方定义

开闭原则( Open Close Principle ),又称为OCP原则,他的官方定义如下:

Software entities like classes,modules and functions should be open for extension but closed for modifications.

一个软件实体如类,模块和函数应该对扩展开放,对修改关闭

基本介绍

对扩展开放指的是提供方,对修改关闭指的是调用方

一个软件产品只要在生命周期内,都会发生变化,即然变化是一个事实,我们就应该在设计时尽量适应这些变化,以提高项目的稳定性和灵活性,真正实现“拥抱变化”,开闭原则告诉我们应尽量通过扩展软件实体的行为来实现变化,而不是通过修改现有代码来完成变化,它是针对软件的未来事件而制定的对现行开发设计进行约束的一个原则

案例演示 - 绘图工具

OK,大家简单了解过开闭原则后,我们来看如下一段代码,帮助大家更深入的理解

有一个绘图工具类,接收 Shape 对象,然后根据不同的 type,来绘制不同的图形,具体代码如下图所示

//这是一个用于绘图的类 [使用方]
class GraphicEditor {

    //接收 Shape 对象,然后根据不同的 type,来绘制不同的图形
    public void drawShape(Shape s) {
        if (s.m_type == 1) {
            drawRectangle(s);
        } else if (s.m_type == 2) {
            drawCircle(s);
        }
    }
    //绘制矩形
    public void drawRectangle(Shape r) {

        System.out.println(" 正在绘制矩形中---绘制成功 ");

    }
    //绘制圆形
    public void drawCircle(Shape r) {

        System.out.println(" 正在绘制圆形中---绘制成功");

    }
}

//Shape 类,基类
class Shape {

    int m_type;
}

class Rectangle extends Shape {

    Rectangle() {
        super.m_type = 1;
    }
}
class Circle extends Shape {

    Circle() {
        super.m_type = 2;
    }

}

上面这段代码首先是可以完成需求的,OK,那现在我们新增绘制三角形的功能,大家想一下实现思路

首先我们要新增 Triangle 类,然后新增绘制三角形的方法, drawShap()方法里添加判断 并调用就Ok,新增代码示例如下图所示

//新增绘制三角形的子类
class Triangle extends Shape {
    Triangle() {
        super.m_type = 3;
    }
}
//类 GraphicEditor 中·添加判断,type=3,绘制三角形
if (s.m_type == 1) {
    drawRectangle(s);
} else if (s.m_type == 2) {
    drawCircle(s);
} else if (s.m_type == 3) {
    drawTriangle(s); 
}

// 类 GraphicEditor 中新增绘制三角形的方法
public void drawTriangle(Shape r) {

    System.out.println(" 正在绘制三角形中---绘制成功 ");
}

案例分析

Ok,上面的代码是比较好理解的,但是大家想一下,针对上面的业务逻辑来说,类 GraphicEditor 扮演的其实是调用方的角色,但是出现了新增的需求后,我们对于 类 GraphicEditor 进行了一系列改动,这显然违背了ocp原则

因为我们上面提到,ocp原则对调用方的修改是关闭的,那大家想一下,新增绘制三角形的功能,我们还可以怎么样实现呢?下面我们在满足ocp原则的情况下,对上面的代码进行重构

解决方案

这时有的小伙伴说了,可以把创建 Shape 类做成抽象类,并提供一个抽象的 draw 方法,让子类去实现即可,这样我们有新的图形种类时,只需要让新的图形类继承 Shape,并实现 draw 方法即可,使用方的代码就不需要修 改了,这样既满足了业务逻辑,又符合开闭原则,具体代码示例如下

//这是一个用于绘图的类 [使用方]
class GraphicEditor {

    //接收 Shape 对象,然后根据不同的 type,来绘制不同的图形
    public void drawShape(Shape s) {
        s.draw();
    }
}

//Shape变为抽象类,并提供抽象draw方法
abstract class Shape {

    int m_type;

    public abstract void draw();//抽象方法

}

class Rectangle extends Shape {

    Rectangle() {
        super.m_type = 1;
    }

    @Override
    public void draw() {
        System.out.println(" 正在绘制矩形中---绘制成功 ");
    }
}

class Circle extends Shape {

    Circle() {
        super.m_type = 2;
    }

    @Override
    public void draw() {
        System.out.println(" 正在绘制圆形中---绘制成功 ");
    }
}

OK,那这样的话,同样还是上面的需求,我们新增绘制三角形的功能,那我们只需要新建一个 类Shape 的子类,实现draw() 方法即可,具体代码示例如下

class Triangle extends Shape {

    Triangle() {
        super.m_type = 3;
    }

    @Override
    public void draw() {
        System.out.println(" 正在绘制三角形中---绘制成功 ");
    }
}

案例总结

通过上面的重构,我们可以看到,当我们新增绘制三角形的功能,不需要修改调用方,即本案例中扮演调用方角色的类 GraphicEditor 不需要修改,而是扩展了提供方的类,来完成需求,就遵守了开闭原则,换句话说,开闭原则要求我们这样做,即 针对提供方,对扩展开放,针对调用方,对修改关闭

注意事项

  • 开闭原则是编程中最基础,最重要的设计原则,只要是面向对象编程,在开发时都会强调开闭原则
  • 开闭原则是最基础的设计原则,其它的五个设计原则都是开闭原则的具体形态,也就是说其它的五个设计原则是指导设计的工具和方法,而开闭原则才是其精神领袖。依照java语言的称谓,开闭原则是抽象类,而其它的五个原则是具体的实现类

  • 开闭原则可以提高复用性和维护性

下节预告

OK,下一节,我们正式进入设计模式原则之迪 米特法则的学习,我会为大家用多个案例分析,来解读设计模式原则之迪米特法则,以及它的注意事项和细节,最后,希望大家在学习的过程中,能够感觉到设计模式的有趣之处,高效而愉快的学习,那我们下期见~

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