深度总结:软件设计七大原则
软件设计七大原则
软件设计原则是设计模式的基石。目的只有一个,降低对象之间的耦合,增加程序的可复用性、可扩展性、可维护性。
开闭原则 OCP
定义:软件实体对扩展开放,对修改关闭。
对扩展开发,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
对修改关闭,意味着类一旦设计完成,就可以独立的工作,而不要对其进行任何的修改。
在面向对象设计中,我们通常通过继承和多态来实现OCP,即封装不变部分。
比如需求要实现2种状态的业务。
如果用if else来判断,那么后面加第三种状态,就还需要在此接口上增加else逻辑,不符合开闭原则。
用策略类实现,则定义策略接口,策略A和策略B为具体实现类,分别对应两种状态。假如下一次需求要实现第三种状态,那么直接定义一个StrategyC实现类就可满足。原有代码不变,符合开闭原则。
详情可点击:策略模式文章
里氏替换原则 LSP
定义:程序中的父类型都可以正确的被子类型替换。
程序中的对象可以在不改变程序正确性的前提下被它的子类所替换,即子类可以替换任何基类能够出现的地方,并且经过替换后,代码还能正确工作。
根据LSP的定义,如果在程序中出现使用instanceof、强制类型转换或者函数覆盖,很可能意味着是对LSP的破坏。
假设定义一个抽象禽类,有一个飞翔方法fly(), 我们就可以自由的继承禽类衍生出各种鸟儿,并调用其飞翔方法。如果鸵鸟加入禽类行列,继承禽类,但不会飞,那么飞翔方法fly()就显得多余。而且在所有禽类出现的地方,无法用鸵鸟替换(此时不满足正确业务逻辑)。违反了里氏替换原则。
经过反思,是设计问题,禽类和飞翔无必然联系,所以禽类不应该定义飞翔方法fly(),把禽类飞翔方法fly()抽离出去单独定义飞翔接口Flyable。
对于有飞翔能力的鸟儿继承禽类并实现飞翔接口。鸵鸟继承禽类,但不实现飞翔接口,是否是鸟儿取决于是否继承自禽类,能不能飞取决于是否实现飞翔接口。所有禽类出现的地方都可以用子类进行替换,所有飞翔接口出现的地方都可以被其替换为实现。
依赖倒置原则 DIP
定义:模块之间交互应该依赖抽象,而非实现。
DIP要求高层模块不应该依赖于底层模块,二者都应该依赖于抽象。抽象不应该依赖细节,细节应该依赖抽象。
比如某个人喂养小动物,如果依赖了具体的实现,则每新增一个动物,需要在Person内加一个对应的方法。违背了开闭原则,也不符合依赖倒置原则。
重新修改后,如下。新增一个Birds抽象类,具体的动物继承自父类Birds,Person中的方法参数依赖于抽象,而不是具体的实现。符合依赖倒置原则。
单一职责原则 SRP
定义:对任何类的修改只能有一个原因。换句话说,一个类只应该负责一项职责。
SRP要求每个软件模块职责要单一,衡量标准是模块是否只有一个被修改的原因。职责越单一,被修改的原因就越少,模块的内聚性就越高,被复用的可能性就越大,也更容易被理解。
举例员工类 Employee,开发工作变了,需要修改Employee类,测试工作变了需要修改Employee类,不符合单一职责原则,类的复杂性也高。
职责多,引起此类变化的原因也多。后续变更的风险就大。
后续需求变更,会造成职责的混乱,类结构的不稳定。
改造后,类的职责单一。开发者的职责就是“写代码”,那么对其进行的修改只有与“写代码”相关的一个原因(画类图也是为了指导代码落地),这样才能确保类职责的单一性原则。
同时,类与类之间虽有着明确的职责划分,但又一起合作完成任务,它们保持着一种“对立且统一”的辩证关系。
以责任链模式为例,每个处理者类职责清晰,只处理与自己职责相关的业务。
以员工类为例,拆分后,各个员工完成相应的职责,共同保障项目上线。
这种清晰的职责范围划分就是单一职责原则的最佳实践。符合单一职责原则的设计能使类具备高内聚性,让单个模块变得简单易懂,如此才能增强代码的可读性和可复用性。并提高系统的易维护性和易测试性。
上面的例子是类职责单一,那么微服务划分也同理,采用单一职责原则,每个服务负责一块业务。同一类业务的变更落在单个服务内变更。
接口隔离原则 ISP
定义:客户端对类的依赖基于最小接口,而不依赖不需要的接口。
接口隔离原则认为不能强迫用户去依赖那些他们不使用的接口。换句话说,使用多个专门的接口比使用单一的总接口要好。做接口拆分时,也要尽量满足单一职责原则。将外部依赖减到最少,降低模块间的耦合。
比如类A只需要使用方法1、方法3,类B只需要使用方法2、方法4,但在源代码层次上与所有方法形成依赖关系。这种依赖意味着我们对接口I的方法2修改,即使不会影响A所依赖的方法1、方法3的功能,也会导致它需要重新部署和编译。
改造后,类A不需要用到方法2、方法4,就可以选择不依赖它们。代码更加清晰,接口职责更加明确。
迪米特法则 LOD
定义:一个类对于其它类知道的越少越好。
迪米特法则也被称为最少知识原则,它提出一个模块对其他模块应该知之甚少,或者说模块之间应该彼此保持陌生,甚至意识不到对方的存在,以此最小化、简单化模块间的通信,并达到松耦合的目的。
反之,模块之间若存在过多的关联,那么一个很小的变动则可能会引发蝴蝶效应般的连锁反应,最终会波及大范围的系统变动。我们说,缺乏良好封装性的系统模块是违反迪米特法则的,牵一发动全身的设计使系统的扩展与维护变的举步维艰。
门面模式和中介者模式是迪米特法则
极好的范例。 Tomcat中 RequestFacade类就使用了外观模式。RequestFacade是对Request类封装,屏蔽内部属性和方法,避免暴露。
合成复用原则 CRP
定义:优先使用合成/聚合,而不是类继承。
比如对象的继承关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其它更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。
合成(组合)和聚合都是关联的特殊种类。
聚合表示一种弱的拥有关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;
合成则是一种强大的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。
合成/聚合复用原则好处:优先使用对象的合成/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模。
举例:手机软件划分可分为QQ、微信等,按品牌划分可分为华为、小米等。如果同时考虑这两种分类,其组合就很多。往下继续扩展软件、手机品牌,都会新增许多子类。违背了开闭原则,也限制了复用性。
用聚合关系实现的类图:后面新增软件,手机品牌类不用变更代码。继承的层次也少了。
参考资料
刘韬:《秒懂设计模式》
张建飞:《代码精进之路:从码农到工匠》
Robert C. Martin:《架构整洁之道》
程杰:《大话设计模式》
关注公众号,后台回复【笔记】获取技术笔记PDF。
深度总结:软件设计七大原则相关推荐
- 【学习笔记】慕课网—Java设计模式精讲 第3章 软件设计七大原则-3-6 迪米特原则(最少知道原则)...
/** * 软件设计七大原则-迪米特原则 学习笔记 * @author cnRicky * @date 2018.11.10 */ 迪米特原则(最少知道原则) 一个对象应该对其他对象保持最少的了解.又 ...
- 设计模式-软件设计七大原则
目录 综述 1.开闭原则 1.1开闭原则的定义 1.2开闭原则的作用 1.3开闭原则的实现方法 2.里氏替换原则 2.1里氏替换原则的定义 2.2里氏替换原则的作用 2.3里氏替换原则的实现方法 3. ...
- 【设计模式】软件设计七大原则
做好自己 软件设计七大原则 开闭原则OCP(Open-Closed Principle) 依赖倒转原则DIP(Dependence Inversion Principle) 单一职责原则SRP(Sin ...
- 【设计模式】软件设计七大原则 ( 接口隔离原则 | 代码示例 )
文章目录 一.接口隔离原则简介 二.接口隔离原则代码示例 ( 反面示例 ) 1.接口定义 ( 接口臃肿 ) 2.实现类 1 3.实现类 2 三.接口隔离原则代码示例 ( 推荐用法 ) 1.接口 1 2 ...
- 软件设计七大原则和设计模式
七大原则 开闭原则 依赖倒置原则 单一职能原则 接口隔离原则 迪米特法则 里氏替换原则 合成复用原则 设计模式 简单工厂 工厂方法模式 抽象工厂模式 建造者模式 单例模式 原型模式 外观模式 装饰者模 ...
- 【设计模式】软件设计七大原则 ( 开闭原则 )
文章目录 一.开闭原则简介 二.开闭原则代码示例 1.商品接口 2.普通商品类 3.折扣商品类 4.测试类 一.开闭原则简介 开闭原则 : 定义 : 一个 软件实体 , 类 / 模块 / 函数 , 对 ...
- 软件设计七大原则实战(二)-开闭原则
1 开闭原则的定义 开闭原则是Java世界里最基础的设计原则,它指导我们如何建立一个稳定的.灵活的系统,先来看开闭原则的定义: Software entities like classes,modu ...
- 【设计模式】软件设计七大原则 ( 里氏替换原则 | 定义 | 定义扩展 | 引申 | 意义 | 优点 )
文章目录 一.里氏替换原则定义 二.里氏替换原则定义扩展 三.里氏替换原则引申意义 四.里氏替换原则意义 五.里氏替换原则优点 一.里氏替换原则定义 里氏替换原则定义 : 如果 对每一个 类型为 T1 ...
- 【设计模式】软件设计七大原则 ( 单一职责原则 | 代码示例 )
文章目录 一.单一职责原则简介 二.单一职责原则代码示例 ( 反面示例 ) 1.不遵循单一职责原则的类 2.测试类 三.单一职责原则代码示例 ( 正面示例 | 类的单一职责 ) 1.用翅膀飞的鸟 2. ...
- 软件设计七大原则:(四)接口隔离原则
一.接口隔离原则简介 用多个专门的接口,而不再使用单一的总接口,客户端不应该依赖它 不需要的接口. 一个类对一个类的依赖应该建立在最小的接口上. 建立单一接口,不要建立庞大臃肿的接口. 尽量细化接口, ...
最新文章
- Umbra 3:次世代的遮挡裁剪
- 字符串比较--小问题大智慧
- 提高CocoaPods速度
- torch.nn.BCELoss are unsafe to autocast
- ant design select 坑总结
- 1.3计算机的性能指标
- Boost:使用/type <>语法测试功能对象
- HDU_2795 Billboard(线段树)
- 如何做到长时间(4 个小时以上)精神专注?
- 剑指offer第12题打印从1到n位数以及大整数加法乘法
- 树莓派 神经网络植入_使用自动编码器和TensorFlow进行神经植入
- 鸟哥的 Linux 私房菜7 -- 首次开机关机与基本指令执行
- ODPS技术架构及应用实践
- Loading动画加载素材模板,UI设计师好帮手
- 2021想学UI设计,你必需要知道这些
- 当归饮(茶):治疗血虚
- 5.23低版本到高版本问题
- 基于python的第三方库Pyautogui实现程序自动控制鼠标与键盘
- 输入12V-48V输出5V-12V电流:2A
- Android手机管理工具类
热门文章
- 使用LOIC 对新搭建的网站迚行DDOS攻击
- 运行Arcgis和SWAT模型遇到Error Number 91和Error Number -2147467259报错怎么办?
- dosbox详细安装级及使用
- 手机输入法带拼音声调_这些神奇的拼音输入法,你都知道几个?
- app抓包工具_【旧版IPA抓包教程2】超便捷苹果旧版本APP抓包/轻松抓取你想要的版本,旧版app任意下载...
- 测试金士顿固态硬盘软件,金士顿固态硬盘管理工具(Kingston SSD Manager)
- 园林景观设计计算机制图,园林景观设计平面图效果图
- Fences报错,explorer.exe未正确关闭问题
- B2B2C多用户商城系统源码 Java商城源码
- JSONP解决前端跨域问题