再谈设计原则—7种设计原则学习总结笔记

这篇文章是对设计模式的再谈系列总结性笔记,推荐阅读C语言中文网上的《软件设计模式概述》html

设计的根本目的是为了解决问题,解决问题的根本前提是要了解到都有哪些问题编程

可靠性/健壮性/可修改性/容易理解/程序简便/可测试性/可扩展性/安全性设计模式

软件设计的七大原则
开闭原则(OPEN CLOSE PRINCIPLE):一个软件实体如类、模块和函数应该对扩展开放,对修改关闭(Software entities should be open for extension,but closed for modification)。安全

目的就是保证程序的扩展性好,易于维护和升级。开闭原则被称为面向对象设计的基石,实际上,其余原则均可以看做是实现开闭原则的工具和手段。意思就是:软件对扩展应该是开放的,对修改是封闭的,通俗来讲就是,开发一个软件时,应该对其进行功能扩展,而在进行这些扩展时,不须要对原来的程序进行修改(不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果)。框架

单一职责原则(Single-Responsibilitiy Principle):一个类负责一项职责,不然类应该被拆分(There should never be more than one reason for a class to change)ide

不能存在多于一个致使类变动的缘由。举个例子:一我的身兼数职,而这些事情相关性不大,甚至有冲突,那他就没法很好的解决这些问题职责,应该分到不一样的人身上去作。函数

单一职责原则是实现高内聚低耦合的最好方法,没有之一。工具

里氏替换原则(Liskov Substitution Principle):继承必须确保超类所拥有的性质在子类中仍然成立(Inheritance should ensure that any property proved about supertype objects also holds for subtype objects)测试

继承与派生的规则:子类能够扩展父类的功能,可是不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽可能不要重写父类的方法。任何基类能够出现的地方,子类必定能够出现。它克服了继承中重写父类形成的可复用性变差的缺点。确保类的扩展不会给已有的系统引入新的错误,下降了代码出错的可能性设计

实现开闭原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,因此里氏代换原则是对实现抽象化的具体步骤的规范。向上转型是Java的基础,咱们常常也用到,实际上,在进行设计的时候,尽可能从抽象类继承,而不是从具体类继承。同时,保证在软件系统中,把父类都替换成它的子类,程序的行为没有变化,就足够了。

LSP是继承复用的基石,只有当衍生类能够替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也可以在基类的基础上增长新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,因此里氏代换原则是对实现抽象化的具体步骤的规范。

依赖倒置原则(Dependence Inversion Principle):高层模块不该该依赖低层模块,二者都应该依赖其抽象;抽象不该该依赖细节,细节应该依赖抽象(High level modules shouldnot depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details. Details should depend upon abstractions)。

依赖倒置原则是实现开闭原则的重要途径之一,它下降了客户与实现模块之间的耦合。

其核心思想是:要面向接口编程,不要面向实现编程。即依赖于抽象而不依赖于具体。这个是开闭原则的基础。高层模块不该该依赖低层模块,两者都应该依赖其抽象;抽象不该该依赖细节;细节应该依赖抽象。写代码时用到具体类时,不与具体类交互,而与具体类的上层接×××互。依赖倒置原则的目的是经过要面向接口的编程来下降类间的耦合性,其须要听从的规则:

每一个类尽可能提供接口或抽象类,或者二者都具有。

变量的声明类型尽可能是接口或者是抽象类。

任何类都不该该从具体类派生。

使用继承时尽可能遵循里氏替换原则。

接口隔离原则(Interface Segregation Principle): 一个类对另外一个类的依赖应该创建在最小的接口上(The dependency of one class to another one should depend on the smallest possible interface)。即:创建单一接口,不要创建庞大臃肿的接口,尽可能细化接口,接口中的方法尽可能少。该原则还有另一个定义:客户端不该该被迫依赖于它不使用的方法(Clients should not be forced to depend on methods they do not use)。以上两个定义的含义是:要为各个类创建它们须要的专用接口,而不要试图去创建一个很庞大的接口供全部依赖它的类去调用。

这个原则的意思是:每一个接口中不存在子类用不到却必须实现的方法,若是否则,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好

接口隔离原则和单一职责都是为了提升类的内聚性、下降它们之间的耦合性,体现了封装的思想,但二者是不一样的:

单一职责原则注重的是职责,而接口隔离原则注重的是对接口依赖的隔离。

单一职责原则主要是约束类,它针对的是程序中的实现和细节;接口隔离原则主要约束接口,主要针对抽象和程序总体框架的构建。

在具体应用接口隔离原则时,应该根据如下几个规则来衡量。

接口尽可能小,可是要有限度。一个接口只服务于一个子模块或业务逻辑。

为依赖接口的类定制服务。只提供调用者须要的方法,屏蔽不须要的方法。

了解环境,拒绝盲从。每一个项目或产品都有选定的环境因素,环境不一样,接口拆分的标准就不一样深刻了解业务逻辑。

提升内聚,减小对外交互。使接口用最少的方法去完成最多的事情。

迪米特法则||最少知道原则(Low of Demeter Principle||Least Knowledge Principle):只与你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)。其含义是:若是两个软件实体无须直接通讯,那么就不该当发生直接的相互调用,能够经过第三方转发该调用。其目的是下降类之间的耦合度,提升模块的相对独立性(低耦合,高内聚)。

就是说:一个类对本身依赖的类知道的越少越好(黑盒模式)。也就是说不管被依赖的类多么复杂,都应该将逻辑封装在方法的内部,经过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。

只与直接的朋友通讯(类之间只要有耦合关系,就叫朋友关系)。耦合分为依赖、关联、聚合、组合等。咱们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。咱们要求陌生的类不要做为局部变量出如今类中。

在运用迪米特法则时要注意如下 6 点。

在类的划分上,应该建立弱耦合的类。类与类之间的耦合越弱,就越有利于实现可复用的目标。

在类的结构设计上,尽可能下降类成员的访问权限。

在类的设计上,优先考虑将一个类设置成不变类。

在对其余类的引用上,将引用其余对象的次数降到最低。

不暴露类的属性成员,而应该提供相应的访问器(set 和 get 方法)。

谨慎使用序列化(Serializable)功能

组合||聚合||合成复用原则(Composition/Aggregation Reuse Principle(CARP) ):尽可能使用组合和聚合,少使用继承的关系来达到复用的原则。若是要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成的,二者都是开闭原则的具体实现规范。

合成复用原则的重要性

一般类的复用分为继承复用和合成复用两种,继承复用虽然有简单和易实现的优势,但它也存在如下缺点。

继承复用破坏了类的封装性。由于继承会将父类的实现细节暴露给子类,父类对子类是透明的,因此这种复用又称为“白箱”复用。

子类与父类的耦合度高。父类的实现的任何改变都会致使子类的实现发生变化,这不利于类的扩展与维护。

它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,因此在运行时不可能发生变化。

采用组合或聚合复用时,能够将已有对象归入新对象中,使之成为新对象的一部分,新对象能够调用已有对象的功能,它有如下优势。

它维持了类的封装性。由于成分对象的内部细节是新对象看不见的,因此这种复用又称为“黑箱”复用。

新旧类之间的耦合度低。这种复用所需的依赖较少,新对象存取成分对象的惟一方法是经过成分对象的接口。

复用的灵活性高。这种复用能够在运行时动态进行,新对象能够动态地引用与成分对象类型相同的对象。

原文:https://www.zhoulujun.cn/html/theory/model/7824.html

相关文章
相关标签/搜索