面向对象的六大原则

前言

咱们都知道面向对象有六大原则,23种设计模式。它们能够指导咱们如何写出更加优秀的代码。六大原则是基础,咱们面向对象编程应该尽可能听从这六大原则,才能写出优秀的代码。java

23种设计模式是前人为咱们总结出的解决某一类问题的办法,经过使用这些模式,咱们能够更好的解决这一类问题。固然 23 种设计模式的设计前提也是创建在六大原则基础之上的。编程

目录

六大原则概念

六大原则是面向对象的六大原则,也就是说,咱们在编写面向对象语言的时候,只有遵照了这六大原则才能写出真正的面向对象。才能拥有面向对象的思想。咱们写的代码符合了这六大原则,有助有提升咱们代码的质量,写出可扩展、可维护、可读性好、低耦合、高内聚的代码。设计模式

固然不符合这些原则,一样也是能够写代码的,只不过写出的代码质量就没有保证了,只能说勉强算是个代码。这比如作人同样,人也是有原则的,符合了这些原则,那就能够作一个堂堂正正的好人,不符合这些原则,也能活着。可是当不断的触犯原则,最后成了一个没有原则的人了,那么结果显然可见。若是随着程序不断的变大,代码不断的没有原则,那么最终的结果就是你的程序没法进行下一步维护了。markdown

总之咱们在写代码的时候要尽可能符合这些原则!才能写出高质量代码!网络

单一职责

单一职责是咱们优化代码的第一步框架

概念

概念:就一个类而言,应该仅有一个引发它变化的缘由函数

概念可能不太好懂,简单来讲就是一个类中应该是一组相关性很高的函数、数据的封装。测试

下面举例子:优化

public class Activity{
  
  // 请求网络加载
  public void requestNet(){
    String url = editText.getText();
    String parmas = editText.getText();
    // 判断是否符合某个条件
    if(xx){
      
    }
    // 继续判断
    if(xxx){
      
    }
    .... 等等省略1000行
  }
  
  class Adapter{
    
  }
  
  // 数据类
  class Data{
    
  }
  
  class Xxx{
    
  }
  
  .....
}
复制代码

像上面的例子就是一个很好的反例表明,把全部的职责所有放到了 Activity 中,把全部的函数功能都放到了 requestNet 中。这样势必形成 Activity 异常的臃肿,只要一个职责发生变化就能引发 Activity 的变化。好比 Adapter 变化,要去 Activity 中修改,等等都会对 Activity 形成变化。requestNet 函数中的功能不够纯粹,里面又包含了不少其余的功能,也会致使一样的问题。this

这也就是概念中提到的,就一个类而言,应该仅有一个引发它变化的缘由。

好处

单一职责的好处很明显,让一个类、函数只负责某一项任务或者功能,能够达到很好的复用效果,代码的可读性也会加强,可读性好了,对应的可维护性也会增长。

固然关于职责的划分是一个很抽象的概念,每一个人的划分都会不一样,单一职责的划分界限并不老是那么清晰,有的时候划分的很细也会带来不方便。这是一个灵活掌握的问题,关键是设计代码的时候有没有考虑到这种思想。

开闭原则

Java 世界里最基础的设计原则,指导咱们如何创建一个稳定的、灵活的系统。

概念

软件中的对象(类、模块、函数等)应该对于扩展是开放的,可是对于修改是封闭的。

在编写代码的过程当中,不是一成不变的,需求的变化、升级、维护等等都须要对代码进行修改,修改的时候就不可避免地将错误引入本来已经测试过的旧代码中,破坏原有系统。所以,当软件需求发生变化的时候,咱们应该优先考虑经过扩展的方式来实现变化,而不是经过修改已有代码来实现。

固然实际开发中扩展和修改是同时存在的。应该尽可能少的去修改代码,想法去扩展代码。

《面向对象软件构造》一书中提到这一原则---开闭原则。这一想法认为,程序一旦开发完成,程序中的一个类的实现只应该因错误而被修改,新的或者改变的特性应该经过新建不一样的类实现,新建的类能够经过继承的方式来重用原有类。

举个简单的例子:

public class Hello{
  BlackPen pen = new BlackPen();
  
  void writeHello(){
    pen.write("hello world");
  }
}

// Pen 类能够写出字
public class BlackPen{
  public void write(String content){
    System.out.println("content");
  }
}
复制代码

上面这个程序中咱们能够经过 BlackPen 类写出字,有一天需求变了要求写出红色的字。

public class Hello{
  BlackPen pen = new BlackPen();
  RedPen redPen = new RedPen();
  void writeHello(String flag){
    switch(flag){
        "XXX":
        	pen.wiite("hello world");
        "YYY":
        	redPen.write("hello world")
    }
  }
}

// BlackPen 类能够写出黑字
public class BlackPen{
  public void write(String content){
    System.out.println(content);
  }
}

// RedPen 类能够写出红字
public class RedPen{
  public void write(String content){
    System.out.println(content);
  }
}
复制代码

这样写经过 switch 来判断要调用那一个,若是继续添加其余颜色的笔就继续添加。这样貌似不错。可是试想 Hello 是你提供给别人的一个框架,那么别人想要继续添加能够写出黄色的 Hello Wrold ,是否是就没有办法了,非得让你去修改 Hello 方法才能够,没有了扩展性。

如今优化成

public class Hello{
  Pen pen = new BlackPen();
  public void setPen(Pen pen){
    this.pen = pen;
  }
  void writeHello(){
 		pen.write("hello world")
  }
}

public interface Pen{
  write(String content);
}

// BlackPen 类能够写出黑字
public class BlackPen implement Pen{
  public void write(String content){
    System.out.println(content);
  }
}

// RedPen 类能够写出红字
public class RedPen implement Pen{
  public void write(String content){
    System.out.println(content);
  }
}
复制代码

这样就能够扩展而不用修改 Hello 内的代码了。

开闭原则,对修改关闭,对扩展开放。并非说彻底的不能修改,好比上面内容,一开始只有一个 BlackPen 的时候,你没有想到扩展,能够那样写,可是随着业务变化,出现了不一样的 Pen。这个时候就须要考虑 Pen 要有可扩展性。就不能重复的在 Hello 类中不断去修改了。而是换一种思路,让其变得具备可扩展。

好处

可使用咱们的程序更加稳定,避免修改带来的错误,增长可扩展性。当一个类中的业务不断的发生变化需求,不断的增长业务判断,就须要考虑到扩展性了。

里氏替换原则

构建扩展性更好的系统

概念

所用引用基类的地方必须能透明地使用其子类的对象。

只要父类能出现的地方,子类就能够出现,并且替换为子类也不会产生任何错误或者异常,使用者可能根本就不须要知道是父类仍是子类。

里氏替换原则就是依赖于继承、多态这两大特性。

其实就是将依赖变成抽象,不依赖于具体的实现。

好比:

public class Window{
  public void show(View child){
    child.draw();
  }
}

public abstract class View{
  public abstract void draw();
  
  public void measure(int width,int height){
    // 测量视图大小
  }
}

public class Button extends View{
  public void draw(){
    // 绘制按钮
  }
}

public class TextView extends View{
  public void draw(){
    // 绘制文本
  }
}
复制代码

Window 是依赖于 View 的,是一个抽象类,Window 是依赖于一个抽象,而不是具体的对象。这个时候传入任何 View 的具体对象都是能够的。

好处

提升扩展性,使其不依赖具体的实现,依赖抽象。

依赖倒置原则

让项目拥有变化的能力

概念

依赖倒置原则指代了一种特定的解耦形式,使得高层次的模块不依赖于低层的模块的实现细节,依赖模块被颠倒了。

依赖倒置的关键点:

  • 高层模块不该该依赖低层模块,二者应该依赖其抽象
  • 抽象不该该依赖细节
  • 细节应该依赖抽象

在 Java 语言中,抽象就是指接口或抽象类。二者都是不能直接被实例化的;细节就是实现类,实现接口或者继承抽象类而产生的类就是细节。

高层模块就是调用端,低层模块就是具体的实现类。也就是调用端不要依赖具体的实现类,而是经过依赖抽象的方式。其实就是面向接口编程。

其实和上面里氏替换原则相似

好处

下降耦合性,不依赖具体细节,依赖抽象,提升可扩展性

接口隔离原则

系统有更好的灵活性

概念

客户端不该该依赖它不须要的接口。另外一种定义:类间的依赖关系应该创建在最小的接口上。接口隔离原则将很是庞大、臃肿的接口拆分红更小的和更具体的接口,这样客户将会只须要知道他们感兴趣的方法。接口隔离原则的目的是系统解开耦合,从而容易重构、更改和从新部署。

其实就是让一个接口尽量的小,方法少,使用户使用起来方便。

好比:一个对象实现了多个接口,有个接口是关闭功能,那么当这个对象想要关闭的时候,调用关闭方法就能够了,由于它实现了多个接口,有多个方法,调用的时候就暴露了其余接口函数。这个时候咱们仅须要它暴露关闭的接口就能够了,隐藏其余接口信息。

好处

使用起来更加方便灵活

迪米特原则

概念

迪米特原则也称为最少知道原则。一个对象应该对其余对象有最少的了解。通俗地讲,一个类应该对须要耦合或调用的类知道得最少,类的内部如何实现与调用者或者依赖者没有关系,调用者或者依赖者只须要知道它的须要的方法就能够了,其余的可一律无论。类与类之间关系越密切,耦合度越大,当一个类发生改变时,对另外一个类的影响也越大。

迪米特原则还能够解释为:只与直接朋友通讯。

也就是说,应该尽量少的与别的朋友通讯,仅与最直接的朋友通讯。

两个对象成为朋友的方式有多种:组合、聚合、依赖等等。

好处

下降依赖、使用简单

总结

这六大原则不是相互独立的,而是互相融合,你中有我,我中有你。

单一职责告诉咱们要尽可能的分离代码,不断的精分代码,不一样的模块实现不一样的功能。这样不会全部功能都融合在一块,方便阅读、维护代码。

开闭原则、里氏替换原则、依赖倒置原则:本质上都是经过抽象来提升扩展性。不依赖具体的实现而依赖抽象,就会增长不少扩展性,抽象能够有须要不一样的实现。

接口隔离原则:和单一职责有相似,就是经过接口细分化,暴露最少的方法。要想有某个功能,只须要实现这个接口就能够了,与其余接口无关。

迪米特原则:尽可能依赖更少的类,尽可能对外界暴露更少的方法

实现这六大原则主要是经过面向接口编程,面向抽象编程。不依赖具体的实现。每一个类都有一个抽象(抽象类、接口)。当高层级模块须要依赖这个类的时候,依赖它的抽象,而不是具体。这个时候就能够灵活的改变其实现了。

相关文章
相关标签/搜索