JAVA 设计模式遵循的六大基本准则

JAVA 设计模式遵循的六大基本准则

1、单一职责原则:(Single Responsibility Pinciple)

   一个类只负责一项职责。 当超过一项职责须要负责时,须要增长新的类来负责新的职责,而不是在类中个性代码。html

  若是一个类承担的职责太多,就是高度地职责耦合,很是不利于扩展功能。这是很是脆弱的设计。 容易发生修改一个地方而影响其余地方的状况。java

       遵循单一职责原则的优势:编程

  1.        下降类的复杂度
  2.        提升类的可读性,提升系统的可维护性
  3.        变动引发的风险下降

2、里氏代换原则:(Liskov Substitution Principle,简称LSP)子类能够扩展父类的功能,但不能改变父类原有的功能

里氏代换原则(Liskov Substitution Principle, LSP):全部引用基类(父类)的地方必须能透明地使用其子类的对象。设计模式

里氏代换原则告诉咱们,在一个软件系统中,子类应该能够替换任何基类可以出现的地方,而且通过替换之后,代码还能正常工做。子类也可以在基类的基础上增长新的行为。架构

      例若有两个类,一个类为BaseClass,另外一个是SubClass类,而且SubClass类是BaseClass类的子类,那么一个方法若是能够接受一个BaseClass类型的基类对象base的话,如:method1(base),那么它必然能够接受一个BaseClass类型的子类对象sub,method1(sub)可以正常运行。反过来的代换不成立,如一个方法method2接受BaseClass类型的子类对象sub为参数:method2(sub),那么通常而言不能够有method2(base),除非是重载方法。函数

      里氏代换原则是实现开闭原则的重要方式之一,因为使用基类对象的地方均可以使用子类对象,所以在程序中尽可能使用基类类型来对对象进行定义,而在运行时再肯定其子类类型,用子类对象来替换父类对象。字体

包含4层含义:spa

  1.         子类能够实现父类的抽象方法,但不能覆盖父类的非抽象方法。
  2.         子类中能够增长本身特有的方法。
  3.         当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
  4.         当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

        不遵循里氏代换原则的后果是,写代码出错的机率会大大增长。.net

 

3、依赖倒置原则(Dependence Inversion Principle,简称DIP)

  定义:1.高层模块不该该依赖低层模块,两者都应该依赖其抽象; 2.抽象不该该依赖细节;细节应该依赖抽象。设计

  问题由来:类A直接依赖类B,假如要将类A改成依赖类C,则必须经过修改类A的代码来达成。这种场景下,类A通常是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操做;假如修改类A,会给程序带来没必要要的风险。

  解决方案:将类A修改成依赖接口I,类B和类C各自实现接口I,类A经过接口I间接与类B或者类C发生联系,则会大大下降修改类A的概率。

       依赖倒置原则基于这样一个事实:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定的多。在java中,抽象指的是接口或者抽象类,细节就是具体的实现类,使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操做,把展示细节的任务交给他们的实现类去完成。

  传递依赖的三种写法: 

1.构造函数传递依赖对象 
2.Setter方法传递依赖对象 
3.接口声明传递依赖对象 

深刻了解能够看:轻松学,浅析依赖倒置(DIP)、控制反转(IOC)和依赖注入(DI)

 4、接口隔离原则(Interface Segregation Principle,简称ISP)

  • 核心思想:类间的依赖关系应该创建在最小的接口上
  • 通俗来说:创建单一接口,不要创建庞大臃肿的接口,尽可能细化接口,接口中的方法尽可能少。也就是说,咱们要为各个类创建专用的接口,而不要试图去创建一个很庞大的接口供全部依赖它的类去调用。

 举例

    问题由来:类A经过接口I依赖类B,类C经过接口I依赖类D,若是接口I对于类A和类B来讲不是最小接口,则类B和类D必须去实现他们不须要的方法。

  举例来讲明接口隔离原则:

(图1  未遵循接口隔离原则的设计)

         这个图的意思是:类A依赖接口I中的方法一、方法二、方法3,类B是对类A依赖的实现。类C依赖接口I中的方法一、方法四、方法5,类D是对类C依赖的实现。对于类B和类D来讲,虽然他们都存在着用不到的方法(也就是图中红色字体标记的方法),但因为实现了接口I,因此也必需要实现这些用不到的方法。

  解决方案:将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们须要的接口创建依赖关系。也就是采用接口隔离原则。

   能够看到,若是接口过于臃肿,只要接口中出现的方法,无论对依赖于它的类有没有用处,实现类中都必须去实现这些方法,这显然不是好的设计。若是将这个设计修改成符合接口隔离原则,就必须对接口I进行拆分。在这里咱们将原有的接口I拆分为三个接口,拆分后的设计如图2所示:

(图2  遵循接口隔离原则的设计)

 

  • 需注意:
  • 接口尽可能小,可是要有限度。对接口进行细化能够提升程序设计灵活性,可是若是太小,则会形成接口数量过多,使设计复杂化。因此必定要适度
  • 提升内聚,低耦合=减小对外交互。每一个模块尽量独立完成本身的功能,不依赖于模块外部的代码。内聚和耦合是密切相关的,同其余模块存在高耦合的模块意味着低内聚,而高内聚的模块意味着该模块同其余模块之间是低耦合。在进行软件设计时,应力争作到高内聚,低耦合。
  • 为依赖接口的类定制服务。只暴露给调用的类它须要的方法,它不须要的方法则隐藏起来。只有专一地为一个模块提供定制服务,才能创建最小的依赖关系。

5、迪米特法则(Law of Demeter,简称LoD)

  迪米特法则有不少种说法,好比:一个类应该应该对其余类尽量了解得最少;类只与直接的朋友通讯等等。可是其最终目的只有一个,就是让类间解耦。

  定义

  •     迪米特法则:Law Of Demeter,LoD。
  •     也被称为最少知识原则,Least Knowledge Principle,LKP。

  就是说一个对象应该对其余对象保持最少的了解。正如最少知识原则这个定义同样,一个类应该对其耦合的其余类或所调用的类知道得最少。所耦合的类内部不管如何复杂,怎么实现的我都不须要知道,我只调用你public出来的这些方法,其余都不用知道。

  参考文档-迪米特法则

 

6、开放封闭原则(Open Close Principle,简称OCP)

  所谓开放封闭原则就是软件实体应该对扩展开放,而对修改封闭(不须要修改接口,就能实现新的需求)。开放封闭原则是全部面向对象原则的核心。软件设计自己所追求的目标就是封装变化,下降耦合,而开放封闭原则正是对这一目标的最直接体现。

  开放封闭原则主要体如今两个方面:

  •    对扩展开放,意味着有新的需求或变化时,能够对现有代码进行扩展(根据接口添加新的实现类),以适应新的状况。
  •    对修改封闭,意味着类一旦设计完成,就能够独立其工做,而不要对类尽任何修改也能知足新的需求。

  为何要用到开放封闭原则呢?

    软件需求老是变化的,世界上没有一个软件的是不变的,所以对软件设计人员来讲,必须在不须要对原有系统进行修改的状况下,实现灵活的系统扩展。

  如何作到对扩展开放,对修改封闭呢?

       实现开放封闭的核心思想就是对抽象编程,而不对具体编程,由于抽象相对稳定。让类依赖于固定的抽象,因此对(抽象类)修改就是封闭的;而经过面向对象的继承和多态机制,能够实现对抽象体的继承,经过覆盖其方法来改变固有行为,实现新的扩展方法,因此对于扩展就是开放的(即对接口添加新的实现类来知足新的需求)。

       对于违反这一原则的类,必须经过重构来进行改善。经常使用于实现的设计模式主要有Template Method模式和Strategy 模式。而封装变化,是实现这一原则的重要手段,将常常变化的状态封装为一个类。

代码参考例子:以银行业务员为例

总结:

  1. 单一职责原则告诉咱们实现类要职责单一;
  2. 里氏替换原则告诉咱们不要破坏继承体系;
  3. 依赖倒置原则告诉咱们要面向接口编程;
  4. 接口隔离原则告诉咱们在设计接口的时候要精简单一;
  5. 迪米特法则告诉咱们要下降耦合。而开闭原则是总纲,他告诉咱们要对扩展开放,对修改关闭。
相关文章
相关标签/搜索