在软件开发中,前人对软件系统的设计和开发总结了一些原则和模式, 无论用什么语言作开发,都将对咱们系统设计和开发提供指导意义。本文主要将总结这些常见的原则,和具体阐述意义。数据库
面向对象的基本原则(solid)是五个,可是在常常被提到的除了这五个以外还有 迪米特法则和合成复用原则等, 因此在常见的文章中有表示写六大或七大原则的; 除此以外我还将给出一些其它相关书籍和互联网上出现的原则;编程
Single-Responsibility Principle, 一个类,最好只作一件事,只有一个引发它的变化。单一职责原则能够看作是低耦合,高内聚在面向对象原则的引伸,将职责定义为引发变化的缘由,以提升内聚性减小引发变化的缘由。设计模式
一个对象应该只包含单一的职责,而且该职责被完整地封装在一个类中。(Every object should have a single responsibility, and that responsibility should be entirely encapsulated by the class.),即又定义有且仅有一个缘由使类变动。点击这里查看高可用架构设计9种方案详解。缓存
注意:单一职责原则提出了一个编写程序的标准,用“职责”或“变化缘由”来衡量接口或类设计得是否合理,可是“职责”和“变化缘由”都是没有具体标准的,一个类到底要负责那些职责?这些职责怎么细化?细化后是否都要有一个接口或类?这些都需从实际的状况考虑。因项目而异,因环境而异。
Open - ClosedPrinciple ,OCP, 对扩展开放,对修改关闭(设计模式的核心原则)安全
一个软件实体(如类、模块和函数)应该对扩展开放,对修改关闭。意思是,在一个系统或者模块中,对于扩展是开放的,对于修改是关闭的,一个 好的系统是在不修改源代码的状况下,能够扩展你的功能。而实现开闭原则的关键就是抽象化。架构
Liskov Substitution Principle,LSP:任何基类能够出现的地方,子类也能够出现;这一思想表现为对继承机制的约束规范,只有子类可以替换其基类时,才可以保证系统在运行期内识别子类,这是保证继承复用的基础。框架
第一种定义方式相对严格:若是对每个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的全部程序P在全部的对象o1都代换成o2时,程序P的行为没有变化,那么类型S是类型T的子类型。函数
第二种更容易理解的定义方式:全部引用基类(父类)的地方必须能透明地使用其子类的对象。即子类可以必须可以替换基类可以从出现的地方。子类也能在基类 的基础上新增行为。微服务
(里氏代换原则由2008年图灵奖得主、美国第一位计算机科学女博士、麻省理工学院教授BarbaraLiskov和卡内基.梅隆大学Jeannette Wing教授于1994年提出。其原文以下:Let q(x) be a property provableabout objects x of type T. Then q(y) should be true for objects y of type Swhere S is a subtype of T. )学习
(Interface Segregation Principle,ISL):客户端不该该依赖那些它不须要的接口。(这个法则与迪米特法则是相通的)
客户端不该该依赖那些它不须要的接口。
另外一种定义方法:一旦一个接口太大,则须要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法便可。
注意,在该定义中的接口指的是所定义的方法。例如外面调用某个类的public方法。这个方法对外就是接口。
Dependency-Inversion Principle 要依赖抽象,而不要依赖具体的实现,具体而言就是高层模块不依赖于底层模块,两者共同依赖于抽象。抽象不依赖于具体,具体依赖于抽象。
高层模块不该该依赖低层模块,它们都应该依赖抽象。抽象不该该依赖于细节,细节应该依赖于抽象。简单的说,依赖倒置原则要求客户端依赖于抽象耦合。原则表述:
(Composite/Aggregate ReusePrinciple ,CARP):要尽可能使用对象组合,而不是继承关系达到软件复用的目的
常常又叫作合成复用原则(Composite ReusePrinciple或CRP),尽可能使用对象组合,而不是继承来达到复用的目的。
就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新对象经过向这些对象的委派达到复用已有功能的目的。简而言之,要尽可能使用合成/聚合,尽可能不要使用继承。
继承复用:实现简单,易于扩展。破坏系统的封装性;从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性;只能在有限的环境中使用。(“白箱”复用)
组合/聚合复用:耦合度相对较低,选择性地调用成员对象的操做;能够在运行时动态进行。(“黑箱”复用)
注意:聚合和组合的区别是什么?
合成(组合):表示一个总体与部分的关系,指一个依托总体而存在的关系(总体与部分不能够分开);好比眼睛和嘴对于头来讲就是组合关系,没有了头就没有眼睛和嘴,它们是不可分割的。在UML中,组合关系用带实心菱形的直线表示。
聚合:聚合是比合成关系的一种更强的依赖关系,也表示总体与部分的关系(总体与部分能够分开);好比螺丝和汽车玩具的关系,螺丝脱离玩具依然能够用在其它设备之上。在UML中,聚合关系用带空心菱形的直线表示。
(Law of Demeter,LoD:系统中的类,尽可能不要与其余类互相做用,减小类之间的耦合度
又叫最少知识原则(Least Knowledge Principle或简写为LKP)几种形式定义:
不要和“陌生人”说话。英文定义为:Don't talk to strangers.
只与你的直接朋友通讯。英文定义为:Talk only to your immediate friends.
每个软件单位对其余的单位都只有最少的知识,并且局限于那些与本单位密切相关的软件单位。
简单地说,也就是,一个对象应当对其它对象有尽量少的了解。一个类应该对本身须要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我不要紧,那是你的事情,我就知道你提供的public方法,我就调用这么多,其余的一律不关心。
在迪米特法则中,对于一个对象,其朋友包括如下几类: (1) 当前对象自己(this); (2) 以参数形式传入到当前对象方法中的对象; (3) 当前对象的成员对象; (4) 若是当前对象的成员对象是一个集合,那么集合中的元素也都是朋友;(5) 当前对象所建立的对象。
任何一个对象,若是知足上面的条件之一,就是当前对象的“朋友”,不然就是“陌生人”。
在狭义的迪米特法则中,若是两个类之间没必要彼此直接通讯,那么这两个类就不该当发生直接的相互做用,若是其中的一个类须要调用另外一个类的某一个方法的话,能够经过第三者转发这个调用。
能够下降类之间的耦合,可是会在系统中增长大量的小方法并散落在系统的各个角落,它可使一个系统的局部设计简化,由于每个局部都不会和远距离的对象有直接的关联,可是也会形成系统的不一样模块之间的通讯效率下降,使得系统的不一样模块之间不容易协调。点击这里查看高可用架构设计9种方案详解。
指对对象之间的信息流量、流向以及信息的影响的控制,主要是对信息隐藏的控制。信息的隐藏可使各个子系统之间脱耦,从而容许它们独立地被开发、优化、使用和修改,同时能够促进软件的复用,因为每个模块都不依赖于其余模块而存在,所以每个模块均可以独立地在其余的地方使用。一个系统的规模越大,信息的隐藏就越重要,而信息隐藏的重要性也就越明显。
封装变化
少用继承 多用组合
针对接口编程 不针对实现编程
为交互对象之间的松耦合设计而努力
类应该对扩展开发 对修改封闭(开闭OCP原则)
依赖抽象,不要依赖于具体类(依赖倒置DIP原则)
密友原则:只和朋友交谈(最少知识原则,迪米特法则)
说明:一个对象应当对其余对象有尽量少的了解,将方法调用保持在界限内,只调用属于如下范围的方法: 该对象自己(本地方法)对象的组件 被看成方法参数传进来的对象 此方法建立或实例化的任何对象
别找我(调用我) 我会找你(调用你)(好莱坞原则)
一个类只有一个引发它变化的缘由(单一职责SRP原则)
严格定义:若是对每个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的全部程序P在全部的对象用o1替换o2时,程序P的行为没有变化,那么类型S是类型T的子类型。
通俗表述:全部引用基类(父类)的地方必须能透明地使用其子类的对象。也就是说子类能够扩展父类的功能,但不能改变父类原有的功能。它包含如下4层含义:
子类能够实现父类的抽象方法,但不能覆盖父类的非抽象方法。
子类中能够增长本身特有的方法。
当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
迪米特法则建议“只和朋友说话,不要陌生人说话”,以此来减小类之间的耦合。
开闭原则要求你的代码对扩展开放,对修改关闭。这个意思就是说,若是你想增长一个新的功能,你能够很容易的在不改变已测试过的代码的前提下增长新的代码。有好几个设计模式是基于开闭原则的,如策略模式,若是你须要一个新的策略,只须要实现接口,增长配置,不须要改变核心逻辑。一个正在工做的例子是 Collections.sort() 方法,这就是基于策略模式,遵循开闭原则的,你不需为新的对象修改 sort() 方法,你须要作的仅仅是实现你本身的 Comparator 接口。
享元模式经过共享对象来避免建立太多的对象。为了使用享元模式,你须要确保你的对象是不可变的,这样你才能安全的共享。JDK 中 String 池、Integer 池以及 Long 池都是很好的使用了享元模式的例子。
欢迎你们加入粉丝交流群: 963944895,免费分享Spring框架、Mybatis框架SpringBoot框架、SpringMVC框架、SpringCloud微服务、Dubbo框架、Redis缓存、RabbitMq消息、JVM调优、Tomcat容器、MySQL数据库教学视频及架构学习思惟导图
既然看到这里了,以为笔者写的还不错的就点个赞,加个关注呗!点关注,不迷路,持续更新!!!