java 七大设计原则之迪米特原则,开闭原则,合成复用原则(文字代码相结合理解)

java 七大设计原则之迪米特原则,开闭原则,合成复用原则 ---文字代码相结合理解

七大设计原则有哪些?

  • 单一职责原则
  • 接口隔离原则
  • 依赖倒转(倒置)原则
  • 里氏替换原则
  • 开闭原则
  • 迪米特法则
  • 合成复用原则

一般你们理解的是前六个,并无合成复用原则java

为何要使用七大设计原则?

  • 代码重用性(相同的代码不用屡次编写);
  • 可读性(编程的规范性,便于其余程序员的阅读和理解);
  • 可拓展性(当须要添加新的功能时,很是的方便也称为可维护性);
  • 可靠性(当咱们添加新的功能后对原来的功能没有影响);
  • 使程序呈现高内聚,低耦合等特性

迪米特原则

迪米特原则定义:git

  • 一个对象应该对其余对象保持最少的了解
  • 类与类的关系越密切,耦合度越大
  • 迪米特法则还有个更简单的定义:只与直接朋友通讯

迪米特法则又叫最少知道原则,即一个类对本身依赖的类知道的越少越好,也就是说,对于被依赖的类无论多复杂,都尽可能将逻辑封装在类的内部,对外提供public方法,不对外泄露信息程序员

什么是直接朋友:github

在一个类中:全局变量,返回值,参数传递就称之为直接朋友,编程

局部变量就称之为陌生朋友设计模式

来看一段通俗易懂的代码:markdown

public class A {}
public class B {}
public class C {}
public class D {}
public class E {}

public class B {
   public A mA;

   public C getC(){
       return null;
   }

   public void showD(){
       D d = new D();
   }

   public void setA(E e){

   }
}
复制代码

在B类中:app

  • public A mA; 全局变量
  • public C getC(){ 返回值
    return null;
    }
  • public void showD(){ 局部变量(违反迪米特原则)
    D d = new D();
    }
  • public void setA(E e){} 参数传递

在这里A,C,E就是B的直接朋友,D就是B的陌生朋友框架

未遵照迪米特原则代码:ide

public class Student{
    String name = "";
    public Student(String name) {
        this.name = name;
    }
}

public class StudentManager {
    public void getStudentNumber(Student student){
        ArrayList<String> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(student.name+i);
            Log.i("dimiter:","如今是第 "+i+"个学生,名字为: "+list.get(i));
        }
        Log.i("dimiter:","总共有 "+list.size()+"个学生 ");
    }
}

//使用代码:
//迪米特原则
StudentManager studentManager = new StudentManager();
studentManager.getStudentNumber(new Student("张三"));
复制代码

分析:

  • 学生类(Student) 有neme参数(学生姓名)
  • 学生管理类(StudentManager)建立10个学生,并输出学生名字

违反迪米特原则代码:

代码图(1.1):

\

为何违反迪米特原则:

迪米特原则又叫作最少知道原则,首先要理解:

  • 何为最少知道原则,意思就是:两个类之间耦合性特别低,耦合性特别低就表明他们之间交互特别少,即一个类对本身依赖的类知道的越少越好,在代码图(1.1)这个例子中能够看出,StudentManager()类对Studnet()类建立了10个学生名字.知道的太多了
  • 不对外泄露信息: 代码图(1.1)红框的代码,应该是在Student()内部完成,而后StudentManager()直接调用的

大白话解释:StudentManager()须要全部学生,正确的应该是Student()吧全部学生直接给StudentManager(),而不是给一个Student()对象,让StudentManager()本身去计算全部学生,在大白话一点就是:我问你要什么你就给我什么,不要让我来计算(一个类对本身依赖的类知道的越少越好),你的东西也别让我知道(不对外泄露信息)

仍是比较绕口,来看看遵照迪米特原则的代码就直接恍然大悟了~

遵照迪米特原则:

public class Student{
    String name = "";///学生名字
    
     ///用来存储全部学生名字
    ArrayList<String> mList = new ArrayList<>();

    public Student(String name) {
        this.name = name;
    }

     /// 遵照迪米特原则 建立10个学生
    public List<String> newStudentName(){
        for (int i = 0; i < 10; i++) {
            mList.add(name+i);
            Log.i("dimiter:","如今是第 "+i+"个学生,名字为: "+mList.get(i));
        }
        return mList;
    }
}

public class StudentManager {
    public void getStudentNumber(Student student) {
        /// 遵照迪米特原则
        List<String> list = student.newStudentName();
        Log.i("dimiter:", "总共有 " + list.size() + "个学生 ");
    }
}

//使用代码:
//迪米特原则
StudentManager studentManager = new StudentManager();
studentManager.getStudentNumber(new Student("张三"));
复制代码

Student()建立10个学生,而后给到StudentManager()遵照了:

最少知道(迪米特)原则一个类对本身依赖的类知道的越少越好而且不对外泄露信息,

一个对象应该对其余对象保持最少的了解

这里的最少了解就是指10个Student()学生

我只知道你有10个学生,无论你这10个学生是怎么来的

效果图(2.1):

开闭原则

开闭原则定义:

  • 开闭原则是编程中最基础,最重要的设计原则
  • 一个软件实体如类,模块和方法应该对拓展开放(对提供方),对修改关闭(对使用方),用抽象构建框架,用实现拓展细节(细节指实现代码)
  • 当软件需求要变化时,尽可能经过拓展软件的实体的行为来实现变化,而不是经过修改已有的代码来实现变化
  • 遵照其余原则,以及使用设计模式的目的就是遵照开闭原则

未遵照开闭原则代码:

//形状类型
public abstract class Shape {
    /** * 用来判断类型 * 1:Circular 圆形 * 2:Rectangle 矩形 */
    int type;
}

//圆形
public class Circular extends Shape {
    public Circular() {
        type = 1;
    }
}

//矩形
public class Rectangle extends Shape {
    public Rectangle() {
        type = 2;
    }
}
//开闭原则Manager类 
public class OpenManager {
    public void showShape(Shape shape){
        if (shape .type == 1) {
            drawCircular(shape);
        }else if (shape.type == 2){
            drawRectangle();
        }
    }

    private void drawRectangle() {
        Log.i("Open","建立矩形 ");
    }
    private void drawCircular(Shape shape) {
        Log.i("Open","建立圆形 ");
    }
}

//使用代码:
 //开闭原则
OpenManager openManager = new OpenManager();
openManager.showShape(new Circular());//建立圆
openManager.showShape(new Rectangle());//建立矩形 
复制代码

效果图(2.2):

为何没有遵照开闭原则:

开闭原则的最关键的定义是:

拓展开放(对提供方),对修改关闭(对使用方),用抽象构建框架,用实现拓展细节(细节指实现代码)

若是说我如今要新加一个三角形我该怎么作呢?

是这样写?

public class Triangle extends Shape{
    public Triangle() {
        type = 3;
    }
}

public class OpenManager {
    public void showShape(Shape shape){
        if (shape .type == 1) {
            drawCircular();//建立圆
        }else if (shape.type == 2){
            drawRectangle();//建立矩形
        }else if(shape.type == 3){
            drawTriangle();//建立三角形
        }
    }
    private void drawTriangle() {
        Log.i("Open","建立三角形 ");
    }
}
//使用代码
//开闭原则
OpenManager openManager = new OpenManager();
openManager.showShape(new Circular());
openManager.showShape(new Rectangle());
openManager.showShape(new Triangle());
复制代码

效果图(2.3):

\

这样写不只在改的过程当中容易致使代码的冲突,并且经过if else判断

若是我有100个图形呢?判断100次吗?

if lese if lese if lese if lese if lese if lese if lese if lese if lese if lese…?

这样写出错率过高了,并且没有遵照到拓展开放,修改关闭

遵照开闭原则代码:

public abstract class Shape {
    public abstract void showShape();
}

public class Circular extends Shape {
    @Override
    public void showShape() {
        Log.i("Open","建立圆形 ");
    }
}

public class Triangle extends Shape{
    @Override
    public void showShape() {
        Log.i("Open","建立三角形 ");
    }
}

public class Rectangle extends Shape {
    @Override
    public void showShape() {
        Log.i("Open","建立矩形 ");
    }
}

public class OpenManager {
    public void showShape(Shape shape){
        //遵照开闭原则
        shape.showShape();
    }
}

//使用代码:
//开闭原则
OpenManager openManager = new OpenManager();
openManager.showShape(new Circular());
openManager.showShape(new Rectangle());
openManager.showShape(new Triangle());
复制代码

分析:

  • 能够看出,即便如今新增长了一个三角形类(Triangle),只要继承自Shape就能够画出来,并且不用if else来判断,代码逻辑很是清晰
  • 这才是真正的对扩展开发,对修改关闭,即便我如今在增长一个椭圆形,我自须要继承自Shape()而后输出一下便可
public class Ellipse extends Shape{
    @Override
    public void showShape() {
        Log.i("Open","我是新建立的椭圆形哦");
    }
}
 //开闭原则
OpenManager openManager = new OpenManager();
openManager.showShape(new Circular());
openManager.showShape(new Rectangle());
openManager.showShape(new Triangle());
openManager.showShape(new Ellipse());//建立椭圆形
复制代码

依赖倒置原则有点相似,只不过依赖倒置原则是经过接口来实现,开闭原则是经过抽象来实现.

合成复用原则

合成复用原则定义:

软件复用时,要尽可能先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现


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

  • 继承复用破坏了类的封装性。由于继承会将父类的实现细节暴露给子类,父类对子类是透明的,因此这种复用又称为“白箱”复用。
  • 子类与父类的耦合度高。父类的实现的任何改变都会致使子类的实现发生变化,这不利于类的扩展与维护。
  • 它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,因此在运行时不可能发生变化

大白话翻译:
尽可能不要继承,若是继承的话子类与父类耦合度高,父类对于子类是透明的.不利于维护,若是非要复用的话可使用组合/聚合的方式.

不了解组合/聚合不要紧,下一章我会详细介绍类与类之间的关系!

设计原则的核心思想

  • 找出应用中可能须要的变化之处,把他们独立出来,不要和那些不须要变化的代码混在一块儿。
  • 面向接口编程,而不是针对实现编程。
  • 为了交互对象之间的松耦合设计而努力。
  • 拓展开放(对提供方),对修改关闭(对使用方),用抽象构建框架,用实现拓展细节(细节指实现代码)

迪米特(最少知道)原则代码

开闭原则

设计模式总结:

  • 开闭(OCP)原则: 拓展开放,修改关闭
  • 接口隔离原则:类之间的依赖关系应该创建在最小的接口上
  • 单一职责原则:一个类负责一项职责,而不是一个类负责一个职责
  • 依赖倒置原则:面向接口编程
  • 里氏替换原则:在继承时,在子类中尽可能不要去重写父类的方法,若是非要使用,可使用聚合,组合,依赖来解决问题,不要修改父类的方法!
  • 迪米特(最少知道)原则:只与直接朋友通讯,一个类对本身依赖的类知道的越少越好,不对外泄露信息
  • 合成复用原则:要尽可能使用组合或聚合的关系来实现,其次在考虑继承

猜你喜欢:

去设计模式/设计原则目录页

原创不易,记得点个赞哦~

相关文章
相关标签/搜索