软件设计设计原则 声明:本文章信息参考了 https://blog.csdn.net/u0/article/details/ 软件设计原则是设计模式的基石。目的只有一个,降低对象之间的耦合,增加程序的可复用性、可扩展性、可维护性。
1、开闭原则(OCP) 定义:软件实体对扩展开放,对修改关闭。 对扩展开发,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。 对修改关闭,意味着类一旦设计完成,就可以独立的工作,而不要对其进行任何的修改。 例如在一个业务中,需求要实现多种状态的业务。 如果用if else来判断,那么后面出现新的状态,就还需要在此接口上增加else逻辑,不符合开闭原则。 用策略类实现,则定义策略接口,策略A和策略B为具体实现类,分别对应两种状态。假如下一次需求要实现第三种状态,那么直接定义一个StrategyC实现类就可满足。原有代码不变,符合开闭原则。 策略模式类关系图如下:
有关策略模式详细介绍请查看:悄悄绽放的海棠花:【行为型-1】设计模式之-策略模式 2、里式替换原则(LSP) 定义:程序中的父类型都可以正确的被子类型替换。 程序中的对象可以在不改变程序正确性的前提下被它的子类所替换,即子类可以替换任何基类能够出现的地方,并且经过替换后,代码还能正确工作。 根据LSP的定义,如果在程序中出现使用instanceof、强制类型转换或者函数覆盖,很可能意味着是对LSP的破坏。 假设定义一个抽象禽类,有一个飞翔方法fly(),我们就可以自由的继承禽类衍生出各种鸟儿,并调用其飞翔方法。如果鸵鸟加入禽类行列,继承禽类,但不会飞,那么飞翔方法fly()就显得多余。而且在所有禽类出现的地方,无法用鸵鸟替换(此时不满足正确业务逻辑)。违反了里氏替换原则。 原始类图:
经过反思,是设计问题,禽类和飞翔无必然联系,所以禽类不应该定义飞翔方法fly(),把禽类飞翔方法fly()抽离出去单独定义飞翔接口Flyable。 对于有飞翔能力的鸟儿继承禽类并实现飞翔接口。鸵鸟继承禽类,但不实现飞翔接口,是否是鸟儿取决于是否继承自禽类,能不能飞取决于是否实现飞翔接口。所有禽类出现的地方都可以用子类进行替换,所有飞翔接口出现的地方都可以被其替换为实现。 更新之后的类图:
3、依赖倒装原则(DIP) 定义:模块之间交互应该依赖抽象,而非实现。 DIP要求高层模块不应该依赖于底层模块,二者都应该依赖于抽象。抽象不应该依赖细节,细节应该依赖抽象。 比如某个人喂养小动物,如果依赖了具体的实现,则每新增一个动物,需要在Person内加一个对应的方法。违背了开闭原则,也不符合依赖倒置原则。
重新修改后,如下。新增一个Birds抽象类,具体的动物继承自父类Birds,Person中的方法参数依赖于抽象,而不是具体的实现。符合依赖倒置原则。
4、单一职责原则 SRP 定义:对任何类的修改只能有一个原因。换句话说,一个类只应该负责一项职责。 SRP要求每个软件模块职责要单一,衡量标准是模块是否只有一个被修改的原因。职责越单一,被修改的原因就越少,模块的内聚性就越高,被复用的可能性就越大,也更容易被理解。 举例员工类 Employee,开发工作变了,需要修改Employee类,测试工作变了需要修改Employee类,不符合单一职责原则,类的复杂性也高。
职责多,引起此类变化的原因也多。后续变更的风险就大。后续需求变更,会造成职责的混乱,类结构的不稳定。 类改造 改造后,类的职责单一。开发者的职责就是“写代码”,那么对其进行的修改只有与“写代码”相关的一个原因(画类图也是为了指导代码落地),这样才能确保类职责的单一性原则。 同时,类与类之间虽有着明确的职责划分,但又一起合作完成任务,它们保持着一种“对立且统一”的辩证关系。 以责任链模式为例,每个处理者类职责清晰,只处理与自己职责相关的业务。 有关责任链模式详细情况请看:悄悄绽放的海棠花:【行为型-2】设计模式之-责任链模式 以员工类为例,拆分后,各个员工完成相应的职责,共同保障项目上线。 这种清晰的职责范围划分就是单一职责原则的最佳实践。符合单一职责原则的设计能使类具备高内聚性,让单个模块变得简单易懂,如此才能增强代码的可读性和可复用性。并提高系统的易维护性和易测试性。
5、接口隔离原则( ISP) 定义:客户端对类的依赖基于最小接口,而不依赖不需要的接口。 接口隔离原则认为不能强迫用户去依赖那些他们不使用的接口。换句话说,使用多个专门的接口比使用单一的总接口要好。做接口拆分时,也要尽量满足单一职责原则。将外部依赖减到最少,降低模块间的耦合。 比如类A只需要使用方法1、方法3,类B只需要使用方法2、方法4,但在源代码层次上与所有方法形成依赖关系。这种依赖意味着我们对接口I的方法2修改,即使不会影响A所依赖的方法1、方法3的功能,也会导致它需要重新部署和编译。
改造后,类A不需要用到方法2、方法4,就可以选择不依赖它们。代码更加清晰,接口职责更加明确。
6、迪米特法则(LOD) 定义:一个类对于其它类知道的越少越好。 迪米特法则也被称为最少知识原则,它提出一个模块对其他模块应该知之甚少,或者说模块之间应该彼此保持陌生,甚至意识不到对方的存在,以此最小化、简单化模块间的通信,并达到松耦合的目的。 反之,模块之间若存在过多的关联,那么一个很小的变动则可能会引发蝴蝶效应般的连锁反应,最终会波及大范围的系统变动。我们说,缺乏良好封装性的系统模块是违反迪米特法则的,牵一发动全身的设计使系统的扩展与维护变的举步维艰。 门面模式和中介者模式是迪米特法则极好的范例。 7、合成复用原则(CRP) 定义:优先使用合成/聚合,而不是类继承。 桥接模式就是合成复用原则的经典应用:悄悄绽放的海棠花:【结构型-2】设计模式之-桥接模式 比如对象的继承关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其它更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。 合成(组合)和聚合都是关联的特殊种类。 聚合表示一种弱的拥有关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分; 合成则是一种强大的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。 合成/聚合复用原则好处:优先使用对象的合成/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模。 举例:手机软件划分可分为sigusoft、等,按品牌划分可分为华为、小米等。如果同时考虑这两种分类,其组合就很多。往下继续扩展软件、手机品牌,都会新增许多子类。违背了开闭原则,也限制了复用性。
用聚合关系实现的类图:后面新增软件,手机品牌类不用变更代码。继承的层次也少了。
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/21283.html