设计模式6大原则-开闭原则
设计模式6大原则-开闭原则
定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
开闭原则理念就是当需求改变时,希望在不改变原有代码的前提下,通过扩展模块、函数来满足新需求。
开闭原则是其他五大原则的实现,也是面向对象程序设计的终极目标,它使软件实体具有一定的适应性、灵活性的同时具备稳定性和扩展性。
为什么要采用开闭原则?
(1) 开闭原则对测试的影响
已经投入使用的代码都是有意义的,需要经过 高压力、异常、错误 等严苛条件测试,换句话说,已有代码很多都是通过验证的代码,因此当提出新需求或者需求变化时,如果要修改原有代码,则所有关联模块都要重新进行单元测试、功能测试、集成测试以及验收测试,对测试是一种浪费也增加毫无意义的测试成本,如果是通过扩展添加模块或者函数来满足需求,只需要对新添加代码进行测试即可
(2) 提高代码复用性
在程序设计时尽量缩小模块、类、函数的粒度,粒度越小,被复用的可能性就越大,复用的好处?减少代码量、易于维护,避免相同的逻辑代码分散在多处(容易出错,即便是复制代码也很难保证每一处都完全相同),避免后期需求修改、bug修改时要在多处改动代码(更难以保证所有地方都能做到完全一致的修改)
(3) 提高软件的可维护性
遵守开闭原则的软件,稳定性高、扩展性好,易于维护。需求变换、增加需求时如果是通过扩展来满足需求,则维护人员无需完全读懂、理解之前功能模块的代码(有的代码有多优秀,有的代码就有多糟糕),所以相对于修改原有代码,维护人员更加希望是扩展。
如何使用开闭原则
(1) 抽象约束
抽象是对一组事务的通用描述,也就表示他可以有很多的可能性,可以跟随需求的变化而变化,因此通过接口或抽象类可以约束一组可能变化的行为,并且可以实现对扩展开放。
- 通过接口或抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的 public
- 参数类型、引用对象尽量使用接口或抽象类,而不是实现类
- 抽象层尽量保持稳定,一旦确定就不要修改
(2) 元数据控制模块行为
元数据:用来描述环境和数据的数据,通俗的说就是配置参数
通过扩展一个子类,修改配置文件,完成业务的变化。
(3) 制定项目章程
规定项目中所有人员必须遵守的约定。
(4) 封装变化
- 将相同的变化封装到一个接口或抽象类中
- 将不同的变化封装到不同的接口或抽象类中
实例
以养宠物为例,养宠物需要喂养、需要陪宠物玩,喂养不同宠物的方式是不同的,养的是宠物狗,需要带它出去溜,需要喂食狗粮,养的是宠物猫则需要用戏猫玩具逗它,需要喂食猫粮,下面看不遵循开闭原则的实现
假如刚开始只考虑养宠物狗,定义一个宠物类
// 宠物类public class Pet{public Pet(string type){ }// 陪宠物玩public void PlayWithPet(){Console.WriteLine("陪宠物狗玩,需要带它出去溜溜");}// 喂食public void Feed(){Console.WriteLine("宠物狗需要用狗粮喂养");}}
现在还想再养一只宠物猫,修改宠物类代码
// 宠物类public class Pet{// 宠物类型private string _type;// 构造函数传入宠物类型public Pet(string type){_type = type;}// 陪宠物玩public void PlayWithPet(){if (_type.CompareTo("Dog") == 0){Console.WriteLine("陪宠物狗玩,需要带它出去溜溜");}else if (_type.CompareTo("Cat") == 0){Console.WriteLine("陪宠物猫玩,需要拿戏猫玩具逗猫玩");}}// 喂食public void Feed(){if (_type.CompareTo("Dog") == 0){Console.WriteLine("宠物狗需要用狗粮喂养");}else if (_type.CompareTo("Cat") == 0){Console.WriteLine("宠物猫需要用猫粮喂养");}}}
虽然实现了新需求,但是原有的两个方法 PlayWithPet() 和 Feed() 都进行了修改,并且多了一些不友好的 if else if 代码,可能导致方法修改错误,并且如果再添加其他宠物类型,依然要修改原有正常运行的代码。
由于宠物猫需要买猫砂盆供其上厕所使用,宠物狗不需要,在 宠物类中再添加一个猫砂盆的方法如下
// 猫砂盆public void CatLitterBox(){if (_type.CompareTo("Cat") == 0){Console.WriteLine("猫砂盆供猫上厕所用");}}
这样的代码设计上是不好的,那么下面看遵循开闭原则的宠物类如何设计
考虑到不同宠物用到的方法大致相同,但是具体实现各不相同,所以就将宠物类抽象出来,定义一个宠物接口 IPet ,宠物猫、宠物狗具体类分别继承该接口,根据自身特殊性,添加不同的方法,类图如下
代码实现如下
// 宠物类接口public interface IPet{// 陪宠物玩void PlayWithPet();// 喂食void Feed();}
宠物狗具体类
// 宠物狗public class Dog : IPet{// 陪宠物玩public void PlayWithPet(){Console.WriteLine("陪宠物狗玩,需要带它出去溜溜");}// 喂食public void Feed(){Console.WriteLine("宠物狗需要用狗粮喂养");}}
宠物猫具体类
// 宠物猫public class Cat : IPet{// 陪宠物玩public void PlayWithPet(){Console.WriteLine("陪宠物猫玩,需要拿戏猫玩具逗猫玩");}// 喂食public void Feed(){Console.WriteLine("宠物猫需要用猫粮喂养");}// 猫砂盆public void CatLitterBox(){Console.WriteLine("猫砂盆供猫上厕所用");}}
设计模式6大原则-开闭原则相关推荐
- 设计模式之王者原则 开闭原则
设计模式之王者原则 开闭原则 为什么说 它--开闭原则是王者原则呢? 因为所有原则都是围绕它来实现的,怎么说呢,为什么会有这么多原则呢,都是为了完成它,只要实现它你的代码就不会有什么大的问题 一.定 ...
- 带你认识六种设计原则(开闭原则、里氏代换原则、依赖倒转原则....)
前言 1. 设计原则 1.1. 开-闭原则 1.2. 里氏代换原则 1.3. 依赖倒转原则 1.4. 接口隔离原则 1.5. 合成/聚合原则 1.6. 迪米特法则 前言 学习设计模式之前先要了解其中的 ...
- 六大设计原则--开闭原则
定义 software entities like classes, modules and functions should be open for extension but closed for ...
- java开闭原则 例子_Java设计原则—开闭原则(转)
开闭原则(Open Closed Principle)是Java世界里最基础的设计原则,它指导我们如何建立一个稳定的.灵活的系统. 定义: 一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. S ...
- 设计模式--6大原则--开闭原则
开闭原则(Open Closed Principle) 开闭原则的核心是:对扩展开放,对改动关闭 白话意思就是我们改变一个软件时(比方扩展其它功能).应该通过扩展的方式来达到软件的改变,而不应爱改动原 ...
- java设计模式之设计原则①开闭原则
定义:一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 强调的是用抽象构建框架,用实现扩展细节. 优点:提高软件系统的可复用性及可维护性 例如: 创建一个Course接口 获取id方法 获取n ...
- 学习设计模式 - 六大基本原则之开闭原则
设计模式总共有六大基本原则,统称为SOLID (稳定)原则,分别是S-单一职责原则(Single Responsibility Principle), O-开闭原则(Open closed Princ ...
- Java设计模式七大原则-开闭原则
开闭原则 基本介绍 开闭原则(Open Closed Principle)是编程中最基础.最重要的设计原则 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方).用抽象构建框 ...
- 设计模式之禅之开闭原则
声明:本文为阅读秦小波所写的<设计模式之禅>所写小结,文章内容可能有部分引述此书. 开闭原则(Open Closed Principle):对扩展开放,对修改关闭 1.定义: 软件实 ...
最新文章
- java 常用方法_Java常用方法总结(持续更新中)
- 前端知识之HTML内容
- 用户输入一个数字,找到所有能够除尽它的数的总个数
- 【Git】认识各种开源协议及其关系
- python实现图形旋转_python轻松实现图片旋转
- java继承的性质_java 继承的特性
- compose应用_带有PostgreSQLDocker Compose for Spring Boot应用程序
- Apache PDFBox命令行工具:无需Java编码
- 华为ensp命令大全_电脑网络:华为交换机基础知识及基本命令配置大全,新手的福音...
- 【报告分享】2019年12月郭广昌混沌课程ppt(附下载链接)
- mysql多语言运营设计_多语言系统的数据库设计
- 【miscellaneous】语音识别工具箱综述和产品介绍
- 关于Centos Linux系统安装Python的问题
- 软件开发模式有哪些?
- 【有利可图网】PS实战系列:PS制作人像印章效果
- 我的前端“先行”之路
- 专家思维模型之马太效应
- ubuntu16.10+cuda8.0+cudnn+caffe+opencv3.2+anaconda2
- (新零售)商户网格化运营 - 阿里云RDS PostgreSQL最佳实践
- 微信企业号加密异常处理:InvalidKeyException
热门文章
- 易班网页版简易刷题:湖南商学院教学评估考试
- Leetcode 1373:二叉搜索子树的最大键值和(超详细的解法!!!)
- java算法集训结果填空题练习1
- c++ thread 带参数编译错误:/usr/include/c++/4.8/functional:1697:61: error: no type named ‘type’ in ‘class st
- PHP初级教程------------------(3)
- Windows下使用MingW编译Jsoncpp链接库
- 重磅发布 | 中汽协携手零数科技发布汽车数据可信存证区块链平台
- 套卷答题表设计(题库)
- 我和我老婆的年度阅读清单
- 简单粗暴 隐藏h5页面在微信端底部出现的白色导航条