定义:就一个类而言,应该仅有一个引发它变化的缘由
为何须要单一职责呢?若是一个类承担的职责过多,就等于把这些职责耦合在一块儿了,一个职责的变化可能会引发其它职责的变化,当变化发生时,设计会遭到意想不到的变化。
咱们看看下面简单的类图,UserDiscount类具备两个方法,一个是获取等级类型,一个是计算折扣价格。
定义:软件实体(类、模块、函数等等)应该是能够扩展的,可是不能够修改的函数
下面来看个播放MP3的例子,MP3和Player都是具体类,MP3直接使用Player播放音乐,可是若是须要播放音频,那么就须要从新修改Player而致使MP3也须要修改。
下面咱们修改下例子而遵循OCP原则测试
这个设计中,IPlayer是一个接口,MP3和Video继承该接口,从此想增长其它类型的播放只须要继承IPlayer就行,无需修改MP3或Video类。
但实际开放中,不管模块多么封闭,都会存在一些没法对之封闭的现象,那就须要有策略的去对待这个问题,模块应该对哪一种变化封闭而作出选型,必须先猜想最有可能发生变化的状况,而后构造出抽象来隔离。
结论:遵循OOP能够带来灵活性、可重用性、以及可维护性。然而,对于应用程序中每一个部分都肆意的进行抽象一样是不行的,这样属于不成熟抽象,咱们只须要把频繁变化的部分进行抽象就行。设计
定义:子类型必须可以替换掉它们的基类型
举个例子,函数a使用的参数是基类B,可是C类继承基类B,但把C作为参数传给了函数a而致使其发生错误,这样就是违反了LSP原则。主要体如今下面四个方面:对象
下面来看下简单类图,违反来SRP原则,定义了一个Rectangle和一个继承自Rectangle的Square,看着是很是符合逻辑的,可是咱们从新设置Rectangle的宽度,会致使Square的宽度也会变更,致使Square出错。
改变一下不符合SRP,咱们再定义一个他们共同的父类Graphics,而后让Rectangle和Square都继承自这个父类。在基类Graphics类中没有赋值方法,所以重设宽高不可能适用于Graphics类型,而只能适用于不一样的具体子类Rectangle和Aquare,所以里氏替换原则不可能被破坏。而且下面的设计也符合OCP原则。
结论:使用LSP,使得程序具备更多的可维护性、可重用性以及健壮性。而LSP是使OCP成为可能的主要原则之一,子类型的可替换性才使得基类类型的模块在无需修改的状况下能够扩展。继承
定义:高层模块不该该依赖于低层模块,两者应该依赖于抽象;抽象不该该依赖于细节,细节应该依赖于抽象。
下面来看下简单例子,用户有多个用户等级类UseOrdinary和UserDiamond,而UserTypeService使用等级类进行相关的逻辑处理,从此若是加强其它用户等级,就须要修改UserTypeService,这样违反类DIP,高层策略没有和低层实现分离,抽象没有和具体细节分离,没有这种分离,高层策略就自动地依赖于低层策略,抽象就自动地依赖于具体细节。
咱们变动下具体的实现方式,抽象出UseType接口,UseOrdinary和UserDiamond继承该接口,而UserTypeService使用了UseType,无论从此增长什么用户等级都无需修改UserTypeService,并对于具体的实现类咱们是无论的,只要接口的行为不发生变化,增长新的用户等级后,上层服务不用作任何的修改。这样设计下降了层与层之间的耦合,能很好地适应需求的变化,大大提升了代码的可维护性。
结论:设置倒置的依赖关系结构,使得细节和策略都依赖于抽象,属于面向对象设计;若是依赖关系不倒置,属于过程化设计。接口
定义:不该该强迫继承类依赖于它们不使用的接口方法,类间的依赖关系应该创建在最小的接口上
使用者依赖了那些它们不使用的方法,就面临着这些未使用的方法改变而带来的变动,无心中致使了它们之间的耦合,下面来看下简单示例,MatchingHandler是一个匹配接口,包含匹配系统ID(handleSystemId)和处理联赛ID(detectLeagueId),MatchMatching和LeagueMatching继承了该接口,但MatchMatching不须要处理处理联赛ID,也继承了该方法,这样方法改变而带来的变动。
咱们在来看下变动后的简单类图,新增了LeagueMatchingHandler(detectLeagueId),LeagueMatching继承了该接口,detectLeagueId方法的变动不会致使MatchMatching也须要变动,只会影响到LeagueMatching。
结论:胖类是这个类过于臃肿,可能会致使使用者产生不正常的耦合关系,该类的修改也会致使使用者的修改。使用接口分解,使用者只须要使用特定的接口,并解除了和胖类的耦合关系。ip
定义:类之间尽量少与其余实体发生相互做用
在开发中,咱们常常提到高内聚低耦合,使各个模块之间的耦合尽可能的低,才能提升代码的复用率,耦合的方式不少,依赖、关联、组合、聚合等。其中,咱们称出现成员变量、方法参数、方法返回值中的类为低耦合,而出如今局部变量中的类则高耦合。也就是说,陌生的类最好不要做为局部变量的形式出如今类的内部。下面咱们来看下例子,定义了Match,Team和Player,Match都引用了Team和Player,Team又引用了Player,这样违反了LOD,致使了Match跟Player耦合增长。
下面咱们来变动下引用,Match只须要引用了Team就行,无需在引用Palyer,由于Team已经引用了Player。这样Match能够打印出相关选手了。
结论:LOD的初衷是下降类之间的耦合,因为每一个类都减小了没必要要的依赖,所以的确能够下降耦合关系,但这样必须会产生一个中介类,由这个中介类来处理类之间的通讯,过多的中介类会致使系统复杂度增大而难以维护。设计的时候须要权衡,保持结构清晰和高内聚低耦合开发