1. 程式人生 > >軟體設計的七大原則

軟體設計的七大原則

七大設計原則

開閉原則
依賴導倒置原則
單一職責原則
介面隔離原則
迪米特原則
里氏替換原則
合成複用原則

設計模式-建立型模式

工廠方法模式
抽象工廠模式
建造者模式
單例模式
原型模式

設計模式-結構性模式

介面卡模式
裝飾者模式
代理模式
外觀模式
橋接模式
組合模式
享元模式

設計模式-行為型模式

策略模式
模板方法模式
觀察者模式
訪問者模式
迭代器模式
責任鏈模式
中介者模式
直譯器模式
狀態模式
命令模式
備忘錄模式

在這裡插入圖片描述

開閉原則

定義:一個軟體實體如類,模組和函式應該對擴充套件開放,對修改關閉。
用抽象構建框架,用實現擴充套件細節
優點:提高軟體系統的可複用性及可維護性
下面給一個程式碼體現開閉原則:

package principle.openClose;

public interface ICourse {
    Integer getId();
    String getName();
    Double getPrice();

}
package principle.openClose;

public class javaCoure implements ICourse {

    private Integer id;
    private String name;
    private Double price;

    public javaCoure(Integer id, String name, Double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    @Override
    public Integer getId() {
        return this.id;
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public Double getPrice() {
        return this.price;
    }
}
package principle.openClose;

public class Test {
    public static void main(String[] args) {
        ICourse javaCoures = new javaCoure(88,"語文",100d);
        System.out.println("課程id:"+javaCoures.getId()+"  課程名稱:"+javaCoures.getName()+"  課程價格:"+javaCoures.getPrice());
    }
}

現在價格要變的話怎麼寫呢?
方法一:在ICourse中加入如下程式碼

Double getDiscountPrice();

在javaCourse中新增如下程式碼

    public Double getDiscountPrice(){
        return this.price*0.8;
    }

有啥問題呢,如果課程很多,那麼所有的課程都要加上這些價格變化的方法。介面不能隨便動,否則作為契約的作用就失去了。
方法二:直接在得到價格的方法中改

    @Override
    public Double getPrice() {
        return this.price;
    }

改成:

    @Override
    public Double getPrice() {
        return this.price*0.8;
    }

有啥問題呢?看起來比上面更簡潔了。和上面一樣,如果課程很多的話,修改的地方也很多,如果需求還要你顯示原價,這就行不通了吧。在複雜一點,如果課程》300元的才進行打折活動,如果後面還加了優惠券的活動呢?
方法三:終極方法
增加一個方法,繼承javaCoure

package principle.openClose;

public class JavaDiscountCourse extends javaCoure {

    public JavaDiscountCourse(Integer id, String name, Double price) {
        super(id, name, price);
    }

    @Override
    public Double getPrice() {
        return super.getPrice()*0.8;
    }

    public Double getOriginPrice(){
        return super.getPrice();
    }
}

依賴倒置原則

定義:高層模組不應該依賴低層模組,二者應該依賴其抽象。
抽象不應該依賴細節;細節應該依賴緩抽象
針對介面程式設計,不應該針對實現程式設計
優點:可以減少類間的耦合性,提高系統穩定性,提高程式碼可讀性和可維護性,可降低修改程式所造成的風險。
請看下面程式碼:

package design.dependenceInVersion;

public class Xwy {
    public void studyJavaCourse(){
        System.out.println("xwy在學習java課程");
    }

    public void studyFECourse(){
        System.out.println("xwy在學習前端課程");
    }
}

再寫一個測試類:

package design.dependenceInVersion;

public class Test {
    public static void main(String[] args) {
        Xwy xwy = new Xwy();
        xwy.studyFECourse();
        xwy.studyJavaCourse();
    }
}

如果要再學習一個課程,就需要在Xwy類中加一個方法。
這是面向實現程式設計,實現類需要經常修改,擴充套件性差。
下面有幾種改進的方法

package design.dependenceInVersion;

public interface Icourse {
    void studyCourse() ;
}
package design.dependenceInVersion;

public class JavaCourse implements Icourse {
    @Override
    public void studyCourse() {
        System.out.println("xwy在學習java課程");
    }
}
package design.dependenceInVersion;

public class EFCourse implements Icourse {
    @Override
    public void studyCourse() {
        System.out.println("xwy在學習前端課程");
    }
}
package design.dependenceInVersion;

public class Xwy {
    private Icourse icourse;



    //v1
//    public void studyFECourse() {
//        System.out.println("FE課程");
//    }
//
//    public void studyJavaCourse() {
//        System.out.println("java課程");
//    }


    //v2
//    public void studyXwyCourse(Icourse icourse){
//        icourse.studyCourse();
//    }

    

    //v3
//    public Xwy(Icourse icourse) {
//        this.icourse = icourse;
//    }
//
//    public void studyXwyCourse(){
//        icourse.studyCourse();
//    }

    //v4
    public void setIcourse(Icourse icourse) {
        this.icourse = icourse;
    }

    public Xwy() {
    }

    public void studyXwyCourse(){
        icourse.studyCourse();
    }
}
package design.dependenceInVersion;

public class Test {
    public static void main(String[] args) {

        //v1
//        Xwy xwy = new Xwy();
//        xwy.studyFECourse();
//        xwy.studyJavaCourse();

//        //v2
//        Xwy xwy = new Xwy();
//        xwy.studyXwyCourse(new JavaCourse());
//        xwy.studyXwyCourse(new EFCourse());

        //v3
//        Xwy xwy = new Xwy(new JavaCourse());
//        xwy.studyXwyCourse();


        //v4
        Xwy xwy = new Xwy();
        xwy.setIcourse(new JavaCourse());
        xwy.studyXwyCourse();
        xwy.setIcourse(new EFCourse());
        xwy.studyXwyCourse();
    }
}

上面有4種寫法
第一種:直接實現Icoure介面,在客戶端需要哪個方法就調哪個方法,Xwy xwy = new Xwy();
xwy.studyFECourse();
xwy.studyJavaCourse();
第二種方法:使用介面方法注入
Xwy xwy = new Xwy();
xwy.studyXwyCourse(new JavaCourse());
xwy.studyXwyCourse(new EFCourse());
第三種方法:使用構造器
Xwy xwy = new Xwy(new JavaCourse());
xwy.studyXwyCourse();
第四種方法:使用set注入
Xwy xwy = new Xwy();
xwy.setIcourse(new JavaCourse());
xwy.studyXwyCourse();
xwy.setIcourse(new EFCourse());
xwy.studyXwyCourse();

單一職責原則

  • 定義:不要存在多於一個導致類變更的原因
  • 一個類/ 介面/方法只負責一項職責
  • 優點:降低類的複雜度、提高類的可讀性,提高系統的可維護性、降低變更的風險

介面隔離原則

  • 定義:用多個專門的介面,二不使用單一的總介面,客戶端不應該依賴他不需要的介面
  • 一個類對應一個類的依賴應該建立在最小的介面上
  • 建立單一介面,不要建立龐大臃腫的介面
  • 儘量細化介面,介面中的方法儘量少
  • 適度原則,一定要適度
  • 優點:符合高內聚低耦合的設計思想,從而使得類具有很好的可讀性、可擴充套件性和可維護性
    下面來先看下程式碼
package design.interfaceGeragion;

public interface IAnimalAction {
    void eat();
    void fly();
    void swim();
}
package design.interfaceGeragion;

public class Dog implements IAnimalAction {
    @Override
    public void eat() {

    }

    @Override
    public void fly() {

    }

    @Override
    public void swim() {

    }
}
package design.interfaceGeragion;

public class Bird implements IAnimalAction {
    @Override
    public void eat() {

    }

    @Override
    public void fly() {

    }

    @Override
    public void swim() {

    }
}

再來看下面的程式碼

package design.interfaceGeragion;

public interface IEatAnimalAction {
    void eat();

}
package design.interfaceGeragion;

public interface IFlayAnimalAction {
    void fly();
}

package design.interfaceGeragion;

public interface ISwrimAction {
    void swim();
}
package design.interfaceGeragion;

public class Bird implements IEatAnimalAction,IFlayAnimalAction {
    @Override
    public void eat() {

    }

    @Override
    public void fly() {

    }

}
package design.interfaceGeragion;

public class Dog implements IEatAnimalAction,ISwrimAction {
    @Override
    public void eat() {

    }
    
    @Override
    public void swim() {

    }
}

這個程式碼比上個程式碼更加靈活

迪米特原則

  • 定義:一個物件對其他物件保持最少的瞭解。又叫最少知道原則
  • 儘量降低類與類之間的耦合
  • 優點:降低類之間的耦合
  • 強調只和朋友交流
  • 朋友:出現在成員變數、方法的輸入、輸出引數中的類稱為成員朋友類,而出現在方法體內部的類不屬於朋友類
    看下面的程式碼
package design.dimiter;

import java.util.List;

public class TeamLeader {
    public void checkNumberOfCourse(List<Coures> couresList){
        System.out.println("線上課程的數量是:"+couresList.size());
    }
}
package design.dimiter;

public class Coures {
}
package design.dimiter;

import java.util.ArrayList;
import java.util.List;

public class Boss {
    public void commandCheakNumber(TeamLeader teamLeader){
        List<Coures> couresList = new ArrayList<>();
        for (int i=0;i<20;i++){
            couresList.add(new Coures());
        }
        teamLeader.checkNumberOfCourse(couresList);

    }
}
package design.dimiter;

public class Test{
    public static void main(String[] args) {
        Boss boss = new Boss();
        TeamLeader teamLeader = new TeamLeader();
        boss.commandCheakNumber(teamLeader);
    }
}

idea生成的類圖如下:
在這裡插入圖片描述
course不應該和boss產生交集,把boss裡的程式碼:

List<Coures> couresList = new ArrayList<>();
        for (int i=0;i<20;i++){
            couresList.add(new Coures());
        }

移到TeamLeader中