开闭原则简单一句话就是,实现应该对扩展开放,对修改关闭,那为什么说它是最重要的一个原则呢,因为它是所有原则中的一个基础,包括后续的设计模式,本身通过设计模式可以解耦,提高软件设计的扩展性,在实际开发过程中,都会碰到类似的一个问题,就是我们有一个需求,要进行开发,不得不把我们的旧代码引入进来,然后我们还要修改旧代码,那么这个是非常容易引入错误的,如果时间紧我们又没有时间重构,所以平时写代码的时候遵循这些原则,是非常有必要的,当然我们在开发的过程中,也可以进行重构,或者局部重构,来提高我们软件系统的扩展性,提高内聚降低耦合,那开闭原则的中心思想就是,我们要用抽象来构建框架,用实现来扩展细节,这些原则还比较抽象,我们就是通过coding来解决这些问题,那我们现在就来学习一下开闭原则,简单的举几个小例子,然后大家再从这个例子中进行体会,我们这个项目是一个空的maven项目,创建包,设计原则
package com.learn.design.principle.openclose;/*** 课程* 他是一个接口* 接口我们最好是以i开头* 正常来说一个课程它是一个实体* 我们可以去写一个类* 有id,name,price三个成员变量* 但是我们是为了演示开闭原则* 因为开闭原则比较抽象* 我们这个例子是相对比较简单的例子* 通过后序的一套课程* 我们会对开闭原则理解更深入* 那我们的课程有很多类型* 有JAVA的* 有算法的* 也有前端的* * 首先回到我们的接口* 首先我们修改了这个接口* 但是我们的接口是不应该经常变化的* 他应该是稳定且可靠的* 否则接口作为契约的效果也就失去了* 那我们再换一种思路* * 为什么一开始的Course是一个接口* 这里是为了演示面向接口编程* * 首先接口没有变* * * @author Leon.Sun**/
public interface ICourse {/*** 这个接口可以返回课程的id* @return*/Integer getId();/*** 课程里面还有name* 课程的名字* 这个也是一个方法* * @return*/String getName();/*** 他里面还有一个价格* * 这里获取原价* * @return*/Double getPrice();/*** 这里获取打折的价格* 我们把这个方法去掉* * @return*/
//    Double getDiscountPrice();}
package com.learn.design.principle.openclose;/*** 我们创建一个类叫JavaCourse* 他实现了ICourse接口* 然后我们来实现这些方法* 那这个实现就比较简单* * 然后这个类也进行了实现* 那假设我们的课程类型很多* 那所有的课程实现类都要实现一下这个方法* 那如果类少我们也就忍了* * 然后我们继续来看这个类* 我们如果通过JavaCourse来写JAVA的一个子类* 我们来试一下* 我们新建一个类* * 他的实现类也没有变* * @author Leon.Sun**/
public class JavaCourse implements ICourse{/*** 声明ID* */private Integer Id;/*** 声明名字* */private String name;/*** 声明他的价格* */private Double price;/*** 声明一个全参构造器* 全部选择* * @param id* @param name* @param price*/public JavaCourse(Integer id, String name, Double price) {/*** 其实这个环境this加不加都是一样的* */this.Id = id;this.name = name;this.price = price;}public Integer getId() {return this.Id;}public String getName() {return this.name;}public Double getPrice() {/*** 我们在这里直接乘以0.8* 看似更简单的完成这个需求* 这次只修改一个类* 我说的只修改一个类* 跟之前方法的两个类* 是相对值* 如果我们的课程还有前端的课程* 还有算法课程* 还有python课程* 那他修改的是一个实现类的个数* 但是有一点是否满足需求呢* 假设需求说我还要显示原价* 这个方法是获取不到原价的* 那再往复杂了说* 如果我们课程大于300元的* 才进行打八折活动呢* 后续再引入优惠券* 所以这个方式我们获取不到原价* */return this.price*0.8;}/*** 那我们的JavaCourse类要进行修改了* 至少我要实现这个方法* 假设现在做活动打八折* 乘以0.8* 看起来我们的需求完成了* 但是我们这种写法我们来看一下* * 这边也不用实现了* * * */
//  @Override
//  public Double getDiscountPrice() {
//      return this.price*0.8;
//  }}
package com.learn.design.principle.openclose;/*** JavaDiscountCourse他来继承JavaCourse* JavaCourse里面没有默认的构造器* 我们在JavaCourse这里并没有一个无参的构造器* 但是那个不重要* 我们还是以课程的目标为准* 这里为什么要命名JavaDiscountCourse* 因为这是一个Java打折的课程* 那如果我们的这个折扣非常的简单* 所有类型的课程都打折* 那我们就可以不叫JavaDiscountCourse* 直接叫做DiscountCourse* 打折的一个课程即可* * 然后我们来声明一个子类来继承JavaCourse* * 虚线的是实现接口* 实线的是继承* 而子类的构造器是调用父类的构造器* 下边的是方法* 一个是返回值是double的* originPrice* 还有一个是返回值的getPrice* 那我们现在的打折销售也完成了* 我们修改的是比较偏应用级的代码* 也就是在应用层的* 而底层的接口* 和底层的基类* 并没有修改* 这样也防止了风险的扩散* 接口里面有很多的方法* 实现类里面逻辑也比较复杂* 那如果我们改折后价的话* 有可能会修改里面的实现* 这个在开发里面都是容易引起bug的* 而我们通过继承了一个基类* 使我们对于扩展是开放的* 而对于修改接口和基类是关闭的* 那我们变化的都是应用层的一个子模块* 比如Test和新增了一个子类* 他影响的范围是越大的* 越高层的影响的范围就越小* 简单的理解* 如果dao层里面变化了* 而这个DAO层被所有service引用* 再上层就是controller* 这个影响就非常大* 有可能我为了改A模块* 所以我们在面向对象编程的时候* 我们一定要强调开闭原则* 其他原则也是开闭原则的一个具体形态* 首先它提高我们的复用性* 而且提高了可维护性* 因为我们并不是一个人单打独斗* 我们要考虑软件的维护成本* 一个典型的例子就是Spring容器* 提供的控制反转* 比如我们会注入一些对象* 来修改源码的一些内容* 就是把控制通过配置文件* 或者bean的配置方式* 而不是去修改Spring的源码* 例如我们通过Spring的特性* 来完成单表登陆的功能* 如果你们团队都遵循开闭原则* 我们的软件项目以后维护起来也会非常容易的* 成本也会非常低* 我通过这个例子简单的介绍一下* 开闭原则* 现在体会不深不要紧* 后续很多的设计模式不断地加强巩固* 那随着我们课程的学习* 大家对这几个原则理解也会越来越深的* 有些设计模式和原则会有冲突* 那其实就是一个平衡的问题* 这个后面再碰到我会详细说的* * * * @author Leon.Sun**/
public class JavaDiscountCourse extends JavaCourse {public JavaDiscountCourse(Integer id, String name, Double price) {/*** IDEA默认给的就是这个*/super(id, name, price);}/*** 从名字上来看* 获取原价* * @return*/public Double getOriginalPrice(){return super.getPrice()*0.8;}/*** 我们复写父类的一个方法* * 我们还是回到这个类里面* * * @return*/public Double getDiscountPrice(){/*** 默认生成的是super.getPrice()* 也就是要调用父类的getPrice方法* 这里面直接乘以0.8* 如果我们这里要做分区间的折扣* 当前的价格大于200的时候* 我们可以打九折* 大于300我们打八折* 这里面我们就直接打折8折* 在这个地方留了一个伏笔* 后边里氏替换原则的时候* 还会回来讲一下这里* * */return super.getPrice()*0.8;}}
package com.learn.design.principle.openclose;/*** 现在我们有一个测试函数* * 我们现在来看一下类结构图* 现在的类结构图非常的简单* ICourse这个是一个接口* JavaCourse这里是一个类* 这个类实现这个接口* 非常清晰* 我们一定要善用IDEA里面的查看工具* 在我们看源码的时候非常有用* 这里和标准的UML有一点小小的差异* 比如I就代表Interface* 也没有用尖括号* 我们能看出来* 这个是他的类型* 现在的类结构也是非常的简单* 我们也输出了信息* 双十一和618要进行一个打折活动* 那我们怎么来开发这个需求呢* * 现在我们回到test里面* * * * * @author Leon.Sun**/
public class Test {public static void main(String[] args) {/*** 我们通过一个接口指向实体类* 第一门课程的ID是96* 名字是"Java从零到企业级电商开发"* 价格是348元* * 这个实现类就是JavaDiscountCourse* JAVA的折扣课程* 课程ID:96 课程名称:Java从零到企业级电商开发 课程原价:278.40000000000003 课程折后价格:222.72000000000003元* 结果出来了* 这里是因为Doble丢失精度的问题* 通过BigDecimal的String构造器* 对于BigDecimal要注意使用String构造器* 那这个不是我们课程的重点* 通过BigDecimal就能够解决他* 那么我们现在接着回来* * 他是一个接口* 对象来指向一个实例* 也可以理解成一个子类的实例* JavaDiscountCourse这个类继承了JavaCourse类* JavaCourse类又实现了ICourse类* 可以简单地理解* 所以实现是JavaDiscountCourse* 但是他的引用是ICourse* 所以我们在这里面想获取原价的时候* 并没有getOriginalPrice* 那我们怎么办啊* 很简单* 我们debug来看一下* 我们看一下JavaDiscountCourse这个类* 我们看到他的类型就是JavaDiscountCourse* 因为我们是使用父类的引用* 所以他拿不到那个pulic方法* * */ICourse iCourse = new JavaDiscountCourse(96, "Java从零到企业级电商开发", 348d);/*** 我们对他直接进行强转* 这样我们就强转成功了* */JavaDiscountCourse javaCourse = (JavaDiscountCourse) iCourse;/*** 然后我们直接输出* System.out.println这个在实际项目中是禁止的* 因为在System.out里面是有锁的* 现在只是一个调试讲解设计模式* 我们就不引入log包了* 就用System.out调试理解即可* 首先是课程ID javaCourse.getId()* 然后呢课程的名称javaCourse.getName()* 然后是课程的价格javaCourse.getPrice()* 单位是元* 课程ID:96 课程名称:Java从零到企业级电商开发 课程原价:348.0 课程折后价格:278.40000000000003元* 现在我们的课程信息都正常输出了* * 课程价格和折扣价格* 现在是直接通过getPrice()拿到的* 那我们的原价没有了* * 课程折后价格* 课程原价还是javaCourse.getOriginalPrice()* */System.out.println("课程ID:" + javaCourse.getId() + " 课程名称:" + javaCourse.getName() + " 课程原价:" + javaCourse.getPrice() + " 课程折后价格:" + javaCourse.getDiscountPrice() + "元");}
}

开闭原则coding相关推荐

  1. python 开闭原则_Python 装饰器@,对函数进行功能扩展操作示例【开闭原则】

    本文实例讲述了Python 装饰器@,对函数进行功能扩展操作.分享给大家供大家参考,具体如下: 装饰器可以对原函数进行功能扩展,但还不需要修改原函数的内容(开闭原则),也不需要修改原函数的调用. de ...

  2. 七大设计原则(一):开闭原则

    参考慕课网视频<Java设计模式精讲>: 视频作者:Geely 视频链接:https://coding.imooc.com/lesson/270.html#mid=17147 定义 一个软 ...

  3. 设计模式六大原则(6)——开闭原则

    定义:一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 问题由来:在软件的生命周期内,因为变化.升级和维护等原因需要对软件原有代码进行修改时,可能会在旧代码中引入错误,也可能会使我们不得不对整 ...

  4. 面向对象软件设计的“开—闭”原则

    1.什么是开闭原则         "开-闭"原则是指软件实体应当对扩展性开放,对修改关闭.即软件实体应该在不修改的前提下扩展,这个原则实际上为软件设计指明了目标.我们知道软件设计 ...

  5. 漫谈面向对象基石之开闭原则(OCP)(转)

    原帖地址: http://www.cnblogs.com/yukaizhao/archive/2010/06/29/ood-ocp.html 开闭原则的意思是软件实体应该对扩展开发,对修改关闭(Sof ...

  6. 一种思路:策略模式 + 反射工厂,很好的实现了开闭原则

    作者 | 麻辣你个王子 来源 | blog.csdn.net/qq_28675967/article/details/90581208 应用场景:某天接到了一个需求,品牌给了一个第三方接口,例如:ww ...

  7. 【设计模式】软件设计七大原则 ( 开闭原则 )

    文章目录 一.开闭原则简介 二.开闭原则代码示例 1.商品接口 2.普通商品类 3.折扣商品类 4.测试类 一.开闭原则简介 开闭原则 : 定义 : 一个 软件实体 , 类 / 模块 / 函数 , 对 ...

  8. 设计模式中的开闭原则

    Table of Contents 1 设计模式中的开闭原则 1.1 基本原则 2 模式中的开-闭原则 2.1 策略模式 2.2 简单工厂 2.3 工厂方法 2.4 抽象工厂 2.5 建造者模式 2. ...

  9. 设计模式--6大原则--开闭原则

    开闭原则(Open Closed Principle) 开闭原则的核心是:对扩展开放,对改动关闭 白话意思就是我们改变一个软件时(比方扩展其它功能).应该通过扩展的方式来达到软件的改变,而不应爱改动原 ...

最新文章

  1. _Linux和安卓之间可以传输文件吗?
  2. python求组合数c_【Python】算法之求组合
  3. Wannafly挑战赛24
  4. 《数据结构上机实验(C语言实现)》笔记(2 / 12):线性表
  5. linux系统atom安装教程,Ubuntu/Linux Mint上安装Atom文本编辑器
  6. 深度学习《再探AE和VAE的区别》
  7. [洪流学堂]Unity2017.3新功能:程序集定义(Assembly Definition File)功能详解
  8. 【信息融合】基于matlab BP神经网络和DS证据理论不确定性信息融合问题【含Matlab源码 2112期】
  9. 农行2021软件开发笔试题
  10. 微信h5开发网页授权-本地如何开发调试?
  11. 联想怎么进入linux界面,联想(Lenovo)为何重返Linux桌面?
  12. websphere html乱码,websphere 乱码问题
  13. ubuntu16.04 双显卡 安装N卡驱动
  14. Python入门: 贪吃蛇详解
  15. whm面板降mysql_在cPanel&WHM 78版上可以取消阻止MySQL 5.5
  16. [易飞]录入信息传递设置信息
  17. Linux--Smba服务搭建
  18. 英才班2019-03测试
  19. 红米k30s至尊纪念版和小米10青春版哪个好
  20. ME3616 NBIOT模块基础使用指南

热门文章

  1. 巴巴运动网学习笔记(36-40)
  2. jQuery 输入框 在光标位置插入内容, 并选中
  3. Abstract Factory(抽象工厂)实践
  4. 重磅!阿里巴巴和全球最大奢侈品电商YNAP成立合资公司
  5. css3 制作平滑过度动画
  6. 使用JavaStcript对数组元素去重的方法
  7. javascript高程3 学习笔记(二)
  8. Delphi DLL制作和加载 Static, Dynamic, Delayed 以及 Shared-Memory Manager
  9. EDM邮件列表清洁的重要性
  10. Exchange 默认数据库删除问题