DesignPattern系列__05开闭原则
介绍
开闭原则是编程设计中最基本、最重要的原则。
定义:一个软件实体如类、方法和模块等,应该对扩展(提供方)开放,对修改(使用方)关闭。用抽象构建框架,用实现扩展细节。
也就是说,在需求发生新的变化时,我们不应该修改原来的代码,而应该通过扩展来满足新的需求。
例子引入
我们要实现一个画图的功能,能够画出圆形、矩形、三角形等,最常见的思路就是利用面向对象的思想,抽象出一个所有图形对象的基类Shape,具体的图形如矩形、圆形灯继承自该类。在Shape中定义一个变量shapeType来保存具体的图形的类型。
定义一个绘图类GraphicEditor,在执行具体的绘图方法(如画一个矩形)时,根据传入的shapeType来执行对应图形的绘制方法。
类图设计如下:

功能初步实现了,但是有什么缺陷吗?让我们来给项目适当的“松松土”:现在我们想要画一个三角形,如何实现呢?
也很简单:再定义一个类Triangle继承自Shape,并且在GraphicEditor修改方法,加入对三角形的类型判断,具体的代码如下:
public class Ocp {
public static void main(String[] args) {
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
graphicEditor.drawShape(new Triangle());
}
}
//这是一个用于绘图的类 [使用方]
class GraphicEditor {
//接收Shape对象,然后根据type,来绘制不同的图形
public void drawShape(Shape s) {
if (s.shapeType == 1)
drawRectangle(s);
else if (s.shapeType == 2)
drawCircle(s);
else if (s.shapeType == 3)
drawTriangle(s);
}
//绘制矩形
public void drawRectangle(Shape r) {
System.out.println(" 绘制矩形 ");
}
//绘制圆形
public void drawCircle(Shape r) {
System.out.println(" 绘制圆形 ");
}
//绘制三角形
public void drawTriangle(Shape r) {
System.out.println(" 绘制三角形 ");
}
}
class Shape {
int shapeType;
}
class Rectangle extends Shape {
public Rectangle() {
super.shapeType = 1;
}
}
class Circle extends Shape {
public Circle() {
super.shapeType = 2;
}
}
//新增画三角形
class Triangle extends Shape {
Triangle() {
super.shapeType = 3;
}
}
OK,新的需求也实现了,现在,发现问题了吗?
我们每次遇见新需求之外,除了定义新的图形类,还要对类GraphicEditor进行修改。
根据前面提到的“开闭原则”中提到的,应该对修改关闭,对扩展开放,我们不应该修改类GraphicEditor,这样会严重影响代码的稳定性和可维护性。
现在,我们尝试按照“开闭原则”来实现这个功能。
根据“开闭原则”,我们应该封装变化,在这里,我们在Shape中定义一个抽象的绘图方法,并在各自实现类内进行具体实现。在类GraphicEditor中,只定义一个接受参数为抽象(Shape)的方法,使得类不再去受到类型影响,满足了“开闭原则”。
具体的代码如下:
public class Ocp {
public static void main(String[] args) {
//使用看看存在的问题
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
graphicEditor.drawShape(new Triangle());
}
}
//这是一个用于绘图的类 [使用方]
class GraphicEditor {
//接收Shape对象,然后根据type,来绘制不同的图形
public void drawShape(Shape s) {
s.draw();
}
}
abstract class Shape {
int shapeType;
//定义一个抽象的画图方法
public abstract void draw();
}
class Rectangle extends Shape {
public Rectangle() {
super.shapeType = 1;
}
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
class Circle extends Shape {
public Circle() {
super.shapeType = 2;
}
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
//新增画三角形
class Triangle extends Shape {
Triangle() {
super.shapeType = 3;
}
@Override
public void draw() {
System.out.println("绘制三角形");
}
}
在改进的代码中,我们将画图方法进行抽象,定义在基类Shape中,并通过子类各自实现对应的画图方法。并且,对于类GraphicEditor而言,只需定义一个接受基类作为参数的方法即可,代码变得整洁、易于维护。
使用注意事项
在实际使用中,需要注意以下几个方面:
1.抽象约束
这点的含义包含三个意思:
1.通过接口或者抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或者抽象类中没有定义的public方法;
2.参数类型,要尽量使用接口或者抽象类,不应该使用实现类。
3.抽象层作为约束,应该尽量保持稳定,一旦确定不容修改。
2.元数据控制模块行为
在实际开发中,要尽量使用注解或者配置文件来控制程序的行为,减少重复开发。比如搭建ssm框架中,使用注解或者配置文件来注入bean。
3.约定优于配置
对于大家普遍遵循的章程或者约定,我们要严格遵守,这样能减少配置文件的编写。比如MyBatis框架对xml文件的扫描,默认会去和接口同名的包下去查找,只要我们遵循这一约定, 就无需格外配置。
4.封装变化
对变化的封装包括两点:
1.相同的变化,应该封装到一个接口或者抽象类中;
2.不同的变化,应该封装到不同的接口或者抽象类中,不应该有两个不同的变化封装在一个接口或者抽象类中。
一句话总结
开闭原则,是一切设计模式的基础,可以说其他原则和设计模式都是为了实现开闭i原则。
DesignPattern系列__05开闭原则的更多相关文章
- C#设计模式系列:开闭原则(Open Close Principle)
1.开闭原则简介 开闭原则对扩展开放,对修改关闭,开闭原则是面向对象设计中可复用设计的基石. 2.开闭原则的实现 实现开闭原则的关键就在于抽象,把系统的所有可能的行为抽象成一个抽象底层,这个抽象底层规 ...
- 深入理解JavaScript系列(7):S.O.L.I.D五大原则之开闭原则OCP
前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第2篇,开闭原则OCP(The Open/Closed Principle ). 开闭原则的描述是: Software ...
- C#软件设计——小话设计模式原则之:开闭原则OCP
前言:这篇继续来看看开闭原则.废话少说,直接入正题. 软件设计原则系列文章索引 C#软件设计——小话设计模式原则之:依赖倒置原则DIP C#软件设计——小话设计模式原则之:单一职责原则SRP C#软件 ...
- 最简单直接地理解Java软件设计原则之开闭原则
写在前面 本文属于Java软件设计原则系列文章的其中一篇,后续会继续分享其他的原则.想以最简单的方式,最直观的demo去彻底理解设计原则.文章属于个人整理.也欢迎大家提出不同的想法. 首先是一些理论性 ...
- 设计原则:开闭原则(OCP)
1.什么是开闭原则 开闭原则的英文是Open Closed Principle,缩写就是OCP.其定义如下: 软件实体(模块.类.方法等)应该"对扩展开放.对修改关闭". 从定义上 ...
- 设计模式之六大原则——开闭原则(OCP)
转载于: http://www.cnblogs.com/muzongyan/archive/2010/08/05/1793454.html 开闭原则(Open Closed Principle)是Ja ...
- 开放-封闭原则(OCP)开-闭原则 和 依赖倒转原则,单一职责原则
单一职责原则 1.单一职责原则(SRP),就一个类而言,应该仅有一个引起它变化的原因 2.如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会消弱或抑制这个类完成其他职责的能力. ...
- [转]设计模式之六大原则——开闭原则(OCP)
原文地址:http://www.cnblogs.com/muzongyan/archive/2010/08/05/1793454.html 开闭原则(Open Closed Principle)是Ja ...
- Head First 设计模式 --3 装饰者模式 开闭原则
装饰者模式:动态的将责任附加到对象上,若要扩展功能,装饰者提供了比集成更有弹性的替代方案.设计原则:1:封装变化2:多用组合,少用继承3:针对接口编程,不针对实现编程4:为对象之间的松耦合设计而努力5 ...
随机推荐
- Android之LinearLayout布局下怎么让按钮固定在底部
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- spring boot 2.0 thymeleaf调试时正常,打包后运行报错. 找不到模板文件.
使用th:fragment 定义模板 使用 th:replace 来添加模板到需要的地方. 使用时发现一个非常奇怪的问题. 本机idea 调试环境一切正常, 但是打成jar包以后报错,提示找不到对 ...
- Effective Java - 构造器私有、枚举和单例
目录 饿汉式单例 静态常量 静态代码块 懒汉式单例 尝试加锁 同步代码块 双重检查 静态内部类单例 枚举单例 Singleton 是指仅仅被实例化一次的类.Singleton代表了无状态的对象像是方法 ...
- 通过字节码分析java中的switch语句
在一次做题中遇到了switch的问题,由于对switch执行顺序的不了解,在这里简单的通过字节码的方式理解一下switch执行顺序(题目如下): public class Ag{ static pub ...
- 截图编辑器 PicPick Biz v4.1.6/v5.0.3 Lite 绿色便携版
下载地址:点我 PicPick 是由NGWIN 软件科技公司推出的一款实用的.多功能屏幕截图与图像编辑神器.软件具备屏幕截取.取色器.调色板.放大镜.标尺.量角器.坐标轴.白板等功能,支持全屏.活动窗 ...
- Java学习笔记之---入门
Java学习笔记之---入门 一. 为什么要在众多的编程语言中选择Java? java是一种纯面向对象的编程语言 java学习起来比较简单,适合初学者使用 java可以跨平台,即在Windows操作系 ...
- MyBatis从入门到精通:各个实体类
SysUser类: package tk.mybatis.simple.model; import java.util.Date; public class SysUser { public Long ...
- 性能测试-实例讲解VU、RPS、RT公式换算
概述 今天看到一篇文章讲解VU.RPS.RT,中间有一个公式如下图 并发数 = RPS * 响应时间 于是我在本地做了几次实验,试图验证一下公式的准确性 实验网站 www.baidu.com 第一次 ...
- java高并发系列 - 第14天:JUC中的LockSupport工具类,必备技能
这是java高并发系列第14篇文章. 本文主要内容: 讲解3种让线程等待和唤醒的方法,每种方法配合具体的示例 介绍LockSupport主要用法 对比3种方式,了解他们之间的区别 LockSuppor ...
- 调用另一个进程,createprocess返回值正确,但被调进程连入口函数都没进入。
1.单独运行被调进程(提示atl不匹配). 2.编译选项设置为不依赖atl即可. 3.启发:能单独测试的,先单独测试.