国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Java編程中必知必會的五條SOLID原則

開發 后端
在本文中,我們介紹SOLID原則的核心內容,并幫助您理解這些原則如何應用到項目中。

在面向對象編程(OOP)領域,SOLID原則是類設計的指導準則。這五個原則形成了一套規則和最佳實踐,開發人員在設計類結構時應遵循這些原則。通過理解和應用這些原則,我們可以發揮出設計模式的潛力,創建強大的軟件架構。

在本文中,我們介紹SOLID原則的核心內容,并幫助您理解這些原則如何應用到項目中。

核心目標:編寫可理解、無回歸和可測試的代碼

SOLID原則的核心目標是構建可理解、無回歸、可讀和可測試的代碼。這些代碼作為一個畫布,多個開發人員可以輕松地進行協作,促進生產力和創新的環境。

現在,我們逐個深入討論SOLID原則,揭示它們在塑造類設計中的重要性。

  • S — 單一責任原則
  • O — 開放封閉原則
  • L — 里氏替換原則
  • I — 接口隔離原則
  • D — 依賴反轉原則

1. 單一責任原則

SOLID的第一個支柱,單一責任原則(SRP),強調一個類應該只有一個變化的原因。遵循這個原則,我們確保每個類只負責一個任務,可使將來的維護和修改更容易。

/*手機類,具有屬性和構造函數*/
Class MobilePhone{
    String brandName;
    Float price;
    Date manufactureDate;
  public MobilePhone(String brandName,Float price,Date manufactureDate){
      this.brandName=brandName;
      this.price=price;
      this.manufactureDate=manufactureDate;
  }
};

/*Invoice類擁有一個手機(mobile phone)和該手機的數量(quantity)*/
Class Invoice{
    private MobilePhone mPhone;
    int quantity;
  public Invoice(MobilePhone mPhone,quantity){
    this.mPhone=mPhone;
    this.quantity=quantity;
  }
  public float calculateTotalPrice(){
    return mPhone.price*this.quantity;//返回發票的總金額
  }
  public void printInvoice(){
    //打印發票的邏輯
  }
  public void sendNotification(){
    //發送通知的邏輯
  }

}

以上代碼,與計算、打印或通知邏輯相關的任何更改都需要修改Invoice類。因此,發票類缺乏明確的關注點分離,對一個方面的修改會影響到其他功能。為了遵循SRP,關鍵是將Invoice類重構為更小、更專注的類, 每個類都獨立處理特定的職責,比如計算、打印或通知邏輯。

根據職責將代碼分離成獨立的類是遵循單一責任原則(SRP)并促進可維護和靈活的代碼庫的正確方法。

在這種設計中,我們應該有:

  • Invoice類只包含計算邏輯。
  • InvoicePrint類只包含打印邏輯。
  • InvoiceNotify類只包含發送通知的邏輯。
/*手機類,具有屬性和構造函數*/
Class MobilePhone{
    String brandName;
    Float price;
    Date manufactureDate;
  public MobilePhone(String brandName,Float price,Date manufactureDate){
      this.brandName=brandName;
      this.price=price;
      this.manufactureDate=manufactureDate;
  }
};

/*發票類,擁有手機和數量屬性*/
Class Invoice{
    private MobilePhone mPhone;
    int quantity;
  public Invoice(MobilePhone mPhone,quantity){
    this.mPhone=mPhone;
    this.quantity=quantity;
  }
  public float calculateTotalPrice(){
    return mPhone.price*this.quantity;//返回發票的總金額
  }
}

Class InvoicePrint{
  private Invoice invoice;
  
  public InvoicePrint(Invoice invoice){
  this.invoice=invoice
  }
  public void printInvoice(){
    //打印發票的邏輯
  }
}/*如果打印邏輯發生變化,只有InvoicePrint類會發生變化。*/
Class InvoiceNotify{
  private Invoice invoice;
  
  public InvoiceNotify(Invoice invoice){
  this.invoice=invoice
  public void sendNotification(){
    //發送通知給用戶的邏輯
  }
}/*如果通知邏輯發生變化,只有InvoiceNotify類會發生變化。*/

2. 開放-封閉原則

第二個原則是開放-封閉原則(OCP),它鼓勵軟件實體對擴展開放,但對修改封閉。換句話說,一旦一個類被建立,它應該能夠輕松地進行擴展,而不需要修改其現有的代碼。這促進了代碼的重用和穩定性。

讓我們以上面使用的InvoiceNotify類為例,InvoiceNotify類經過測試,并且當前在客戶端中實際使用,通過電子郵件發送發票通知。

現在有一個客戶需求,他們需要通過推送通知發送通知。

Class InvoiceNotify{
  private Invoice invoice;
  
  public InvoiceNotify(Invoice invoice){
  this.invoice=invoice
  public void sendNotification(){
    //發送通知給用戶的邏輯
  }
  public void sendPushNotification(){
    //發送推送通知給用戶的邏輯
  }
}

以上代碼,通過在現有類中添加一個新方法,我們違反了開放/封閉原則

與其在現有類中添加一個新方法,我們應該設計一個接口并在各個類中實現。

Interface InvoiceNotification{
 public void sendNotification();
}
Class EmailNotification implements InvoiceNotification{
 private Invoice invoice;
  public EmailNotification(Invoice invoice){
     this.invoice=invoice;
  }
  @Override
  public void sendNotification(){
  //通過電子郵件發送通知的邏輯
  }
}
Class PushNotification implements InvoiceNotification{
 private Invoice invoice;
  public PushNotification(Invoice invoice){
     this.invoice=invoice;
  }
  @Override
  public void sendNotification(){
  //發送推送通知的邏輯
  }
}

如果進一步增強需求,需要通過短信發送通知,無需修改現有類。相反,我們可以創建一個名為TextNotification的新類,它實現了InvoiceNotification接口并重寫了sendNotification()方法。這樣,我們就能夠順利地集成新功能,而不會破壞現有的代碼庫。

3. 里氏替換原則

里氏替換原則(LSP)定義了基類和派生類之間的契約。它規定派生類應該能夠替代其基類,而不會影響程序的正確性。實質上,遵循這個原則可以確保繼承被謹慎地使用,并保持類層次結構的完整性。

例如:在數學中,正方形可以被歸類為矩形的一種特殊形式。它們之間的“是一個”關系可能會導致我們考慮在代碼中使用繼承來建模這種關系。然而,將正方形實現為矩形的派生類可能會導致意外的行為。

在數學中,正方形確實是矩形的一種特殊形式,正如“是一個”關系所暗示的那樣。這往往會引誘我們在代碼中使用繼承來建模這種關系。然而,將正方形實現為矩形的派生類可能會導致意想不到和違反直覺的行為。

我們用一個簡單的Java代碼示例來說明這個問題:

class Rectangle {
    protected int width;
    protected int height;

    public void setWidth(int width) {
        this.width = width;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int calculateArea() {
        return width * height;
    }
}

class Square extends Rectangle {
    @Override
    public void setWidth(int width) {
        this.width = width;
        this.height = width; // 正方形的邊長始終相等,所以兩個維度都設置為相同的值。
    }

    @Override
    public void setHeight(int height) {
        this.height = height;
        this.width = height; // 正方形的邊長始終相等,所以兩個維度都設置為相同的值。
    }
}

public class Main {
    public static void main(String[] args) {
        Rectangle rectangle = new Square();
        rectangle.setWidth(5);
        rectangle.setHeight(3);

        System.out.println("Area: " + rectangle.calculateArea());
    }
}

在這個例子中,我們有一個基類Rectangle,其中包含setWidth和setHeight方法,分別用于設置矩形的寬度和高度。Square類繼承Rectangle類,并重寫這些方法,以確保兩個維度保持相等,以保持正方形的特性。

在主方法中,我們創建一個Rectangle引用,指向一個Square對象。當我們嘗試為寬度和高度設置不同的值(分別為5和3)時,我們得到了一個邊長為3的正方形,而不是實際寬度為5、高度為3的矩形。因此,計算得到的面積(9)與我們期望從寬度為5、高度為3的矩形得到的面積不符。

這個場景展示了里氏替換原則被違反的情況,通過Rectangle引用使用Square對象導致了意外的行為。

為了解決Square繼承Rectangle的問題,我們需要重新評估繼承關系和類設計。一種方法是在這種情況下避免使用繼承,而是專注于公共接口或組合。我們用Java代碼來說明解決方案:

interface Shape {
    int calculateArea();
}

class Rectangle implements Shape {
    protected int width;
    protected int height;

    public void setWidth(int width) {
        this.width = width;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    @Override
    public int calculateArea() {
        return width * height;
    }
}

class Square implements Shape {
    protected int side;

    public void setSide(int side) {
        this.side = side;
    }

    @Override
    public int calculateArea() {
        return side * side;
    }
}

public class Main {
    public static void main(String[] args) {
        Shape rectangle = new Rectangle();
        rectangle.setWidth(5);
        rectangle.setHeight(3);
        System.out.println("矩形面積: " + rectangle.calculateArea());

        Shape square = new Square();
        square.setSide(5);
        System.out.println("正方形面積: " + square.calculateArea());
    }
}

在這個解決方案中,我們引入了一個名為Shape的公共接口,定義了calculateArea()方法。現在,Rectangle和Square都實現了這個接口。Rectangle類保留了setWidth和setHeight方法,而Square類有一個setSide方法。每個類根據自己特定的屬性計算面積。

現在,在main方法中,我們為Rectangle和Square對象分別創建了不同的Shape引用。我們可以適當設置尺寸而不會遇到任何問題。

通過使用組合和共同接口,我們確保每個形狀都能獨立運作,并且按預期運行,而不違反里氏替換原則。這種設計使我們能夠優雅地處理不同的形狀,促進了更清晰和可維護的代碼庫。

4. 接口隔離原則

接口隔離原則(ISP)建議客戶端不應被強迫依賴于它們不使用的接口。與其擁有龐大而笨重的接口,更好的做法是創建小而專注的接口,以滿足客戶端的特定需求。

讓我們通過一個簡單的Java代碼示例來說明ISP:

假設我們有一個名為Printer的接口,提供打印功能:

interface DocumentProcessor {
    void print();
    void fax();
}

class LaserPrinter implements DocumentProcessor {
    @Override
    public void print() {
        System.out.println("Printing with a laser printer.");
    }

    @Override
    public void fax() {
        System.out.println("Sending a fax with a laser printer.");
    }
}

class FaxMachine implements DocumentProcessor {
    @Override
    public void print() {
        // 傳真機無法打印,所以將這個方法保持為空。
    }

    @Override
    public void fax() {
        System.out.println("Sending a fax with a fax machine.");
    }
}

這個設計的問題在于FaxMachine類對于print()方法沒有有意義的實現,因為傳真機無法打印文檔。盡管如此,FaxMachine類仍然被強制實現print()方法,這是因為DocumentProcessor接口的設計。

這種對接口隔離原則的違反顯而易見,因為FaxMachine類現在需要實現它不需要或使用的方法。

5. 依賴反轉原則

SOLID原則的最后一塊拼圖是依賴反轉原則(Dependency Inversion Principle,DIP)。該原則主張高層模塊不應依賴于低層模塊,而應依賴于抽象。通過遵循這一原則,我們實現了解耦,從而增強了靈活性、可維護性和測試的便捷性。

讓我們通過一個小的Java代碼示例來說明違反依賴反轉原則的情況:

假設我們有一個ReportGenerator類,它直接依賴于一個DatabaseConnection類:

class DatabaseConnection {
    public void connect() {
        System.out.println("Connected to the database.");
    }

    public void executeQuery(String query) {
        System.out.println("Executing query: " + query);
    }

    public void close() {
        System.out.println("Connection closed.");
    }
}

class ReportGenerator {
    private DatabaseConnection databaseConnection;

    public ReportGenerator() {
        this.databaseConnection = new DatabaseConnection();
    }

    public void generateReport() {
        databaseConnection.connect();
        databaseConnection.executeQuery("SELECT * FROM data_table");
        databaseConnection.close();
        System.out.println("Report generated successfully.");
    }
}

在這段代碼中,ReportGenerator類在其構造函數中直接創建了一個DatabaseConnection實例。結果,ReportGenerator與DatabaseConnection緊密耦合。對DatabaseConnection類的任何更改都可能會影響到ReportGenerator。

為了解決這個問題,我們需要應用依賴反轉原則,引入一個兩個類都依賴的接口:

interface Connection {
    void connect();
    void executeQuery(String query);
    void close();
}

class DatabaseConnection implements Connection {
    @Override
    public void connect() {
        System.out.println("Connected to the database.");
    }

    @Override
    public void executeQuery(String query) {
        System.out.println("Executing query: " + query);
    }

    @Override
    public void close() {
        System.out.println("Connection closed.");
    }
}

class ReportGenerator {
    private Connection connection;

    public ReportGenerator(Connection connection) {
        this.connection = connection;
    }

    public void generateReport() {
        connection.connect();
        connection.executeQuery("SELECT * FROM data_table");
        connection.close();
        System.out.println("Report generated successfully.");
    }
}

public class Main {
    public static void main(String[] args) {
        Connection databaseConnection = new DatabaseConnection();
        ReportGenerator reportGenerator = new ReportGenerator(databaseConnection);

        reportGenerator.generateReport();
    }
}

通過遵循依賴反轉原則,我們通過Connection接口解耦了ReportGenerator和DatabaseConnection類。這種方法允許我們在不修改ReportGenerator的情況下輕松切換和擴展Connection接口的實現。現在的代碼符合原則,更易于維護和靈活。

結論

SOLID原則是面向對象類設計的基石,對于每個尋求創建高效、可維護和協作的軟件的開發人員來說至關重要。當你踏上編碼之旅時,請記住SOLID運用原則!

責任編輯:趙寧寧 來源: Java學研大本營
相關推薦

2025-10-30 07:20:00

2024-06-19 10:08:34

GoChannel工具

2010-08-04 14:32:33

求職

2015-08-17 16:05:35

javascript對象編程

2023-12-26 12:10:13

2020-07-10 07:58:14

Linux

2024-11-15 11:11:48

2024-01-10 18:01:22

編程技巧Java 12

2024-01-03 07:56:50

2022-05-18 09:01:19

JSONJavaScript

2018-10-26 14:10:21

2023-05-08 15:25:19

Python編程語言編碼技巧

2023-04-20 14:31:20

Python開發教程

2022-08-19 10:31:32

Kafka大數據

2024-07-26 08:32:44

panic?Go語言

2021-06-09 11:06:00

數據分析Excel

2020-08-23 18:18:27

Python列表數據結構

2023-10-19 21:30:36

架構CQRS模式

2021-01-20 15:43:01

機器學習深度學習科學

2015-10-20 09:46:33

HTTP網絡協議
點贊
收藏

51CTO技術棧公眾號

国产成人aa在线观看网站站| 精品国产乱码久久久久软件| 男女视频在线看| 日本在线观看不卡视频| 日本韩国欧美精品大片卡二| 成人免费在线观看视频| 欧美精品一区二区三区一线天视频| 夜色资源站国产www在线视频| 久久久美女毛片| 久久视频这里有精品| 日韩电影在线免费| 蜜桃av久久久亚洲精品| 欧美日韩国产一区精品一区| 国产精品va在线播放| 久久av网站| 亚洲视频精品在线| 国产在线美女| 91精品国产一区二区| 999在线视频| 欧美日韩精品系列| 日本不卡三区| 日韩欧美精品在线视频| 成人ww免费完整版在线观看| 3d成人动漫网站| 日韩激情美女| 日韩av一区在线| 国产亚洲一区二区手机在线观看| 亚洲第一精品福利| 欧美日韩精品免费观看视完整| 亚洲裸体xxxx| 国产精久久一区二区| 爱福利视频一区| 波多野结衣一区二区三区免费视频| 久久久久久av| 日韩精品dvd| 精品不卡一区二区三区| 奇米888四色在线精品| 四虎永久免费网站| 国产毛片一区二区| 色一情一乱一伦一区二区三区日本| 欧美激情综合网| 在线观看成年人视频| 亚洲国产欧美在线| 日本www在线| 亚洲午夜激情免费视频| 高清不卡一区| 国产精品久久久久久久久久新婚| 欧美二区视频| 欧美 日韩 国产 在线观看| 99久久99久久综合| 亚洲精选av在线| 91精品国产综合久久久蜜臀图片| 欧美大片1688| 69av在线视频| 亚洲每日在线| 成人免费a级片| 亚洲欧美另类在线| av女优在线| 一夜七次郎国产精品亚洲| 日韩理论电影中文字幕| 999日本视频| 国产乱码字幕精品高清av| 日日碰狠狠躁久久躁婷婷| 一区二区三区四区蜜桃 | 国产精品99一区二区三区| 免费试看一区| 久久久久久久久一| av在线日韩国产精品| 亚洲香蕉av在线一区二区三区| 亚洲精品合集| 天堂av免费看| 狠狠综合久久av一区二区小说| 小早川怜子影音先锋在线观看| 日本久久久久久久| 麻豆精品视频在线观看免费| 4kfree性满足欧美hd18| 精品日韩99亚洲| 蜜臀av免费一区二区三区| 日韩激情久久| 亚洲一区二区三区免费视频| 九色porny丨首页入口在线| 国产精品444| 高清shemale亚洲人妖| 日本天堂影院在线视频| 精品国产一区二区在线| 一本色道久久综合亚洲精品高清 | 亚洲福利在线播放| 精品国产一区二区三区久久久樱花 | 欧美在线www| 国产精品一区二区三区99| 在线激情av| 大胆欧美人体视频| 老司机午夜精品视频| 日本不卡1区2区3区| 亚洲天堂网在线观看| 伊人久久亚洲美女图片| av在线天天| 久久精品国产亚洲精品2020| 久久精品系列| 日韩在线免费播放| 欧美怡春院一区二区三区| 国产成人av自拍| 3d玉蒲团在线观看| 99久热re在线精品视频| 国产精品久久久久久久久图文区 | 亚洲一区三区| 在线观看欧美黄色| 精品成av人一区二区三区| 男女激情免费视频| 亚洲精品一区二区三区香蕉| 91av精品| 最近最新中文字幕在线| 91高清视频免费| 国产午夜精品一区二区三区嫩草| а√在线中文网新版地址在线| 国产精品二区二区三区| 亚洲主播在线观看| 婷婷综合成人| 999sesese| 成人在线免费观看黄色| 国产日产欧美a一级在线| 欧美国产亚洲另类动漫| 国产原创一区| 日韩欧美一区三区| 日韩专区中文字幕| 91在线播放网址| 免费欧美网站| 久久久久人妻精品一区三寸| 亚洲精品少妇网址| 激情久久久久久久久久久久久久久久| 成人ww免费完整版在线观看| 蜜桃av噜噜一区二区三区| 欧美高清激情brazzers| 男人的天堂亚洲在线| 亚洲www色| 国产精品美女在线播放| 亚洲天堂av在线免费| 北条麻妃国产九九精品视频| 99精品美女视频在线观看热舞 | 亚洲日韩中文字幕| 久久se这里有精品| 中文字幕一区久| www.日本在线视频| 色777狠狠综合秋免鲁丝| 97久久精品人人做人人爽| 久久国际精品| 黄a免费视频| 97人人模人人爽视频一区二区| 欧美特级限制片免费在线观看| 国产精品美女久久久| av日韩国产| 99爱视频在线| 国产suv精品一区二区三区88区| 午夜视频在线观看一区二区三区 | 成人黄色网址| 欧美aaa在线观看| 久久视频精品在线| 中文字幕中文字幕中文字幕亚洲无线| 国产成人一区| 黄网站app在线观看| 8x8x华人在线| 欧美一级片免费在线| 91久久线看在观草草青青| 视频一区二区三区入口| 亚洲成人不卡| 99热手机在线观看| av噜噜色噜噜久久| 亚洲欧美综合图区| 一区二区三区在线观看动漫| 狠色狠色综合久久| 色豆豆成人网| 疯狂做受xxxⅹ高潮视频免费| 97在线中文字幕| 亚洲激情视频在线观看| 久久久久久久国产精品影院| 久久影院100000精品| 欧美1—12sexvideos| 欧美视频在线播放一区| 国产精品一区久久久| 精品久久五月天| 中文字幕av在线一区二区三区| 欧美一区免费| 久久人体av| 国产尤物视频在线| 国产精品久久中文字幕| 成人午夜在线观看| 亚洲天堂免费在线| 婷婷激情综合网| 成人黄色大片在线观看| 久久美女视频| 久久国产三级| a天堂在线资源| 国产精品69页| 欧美精品一区二区三区久久| 久久亚洲精品网站| 欧美精品在线观看播放| 久久精品亚洲精品国产欧美kt∨| 亚洲激精日韩激精欧美精品| 一本久道久久综合中文字幕| 亚洲成av人影片在线观看|