開閉原則——面向對象程式設計原則

  • 2019 年 10 月 6 日
  • 筆記

目錄


前言

在軟體開發中,為了提高軟體系統的可維護性和可復用性,增加軟體的可擴展性和靈活性,程式設計師要盡量根據 7 條原則來開發程式,從而提高軟體開發效率、節約軟體開發成本和維護成本。我們將在下面的幾節中依次來介紹這 7 條原則,本節首先介紹開閉原則。

開閉原則定義

開閉原則規定「軟體中的對象(類,模組,函數等等)應該對於擴展是開放的,但是對於修改是封閉的」,這意味著一個實體是允許在不改變它的源程式碼的前提下變更它的行為。該特性在產品化的環境中是特別有價值的,在這種環境中,改變源程式碼需要程式碼審查,單元測試以及諸如此類的用以確保產品使用品質的過程。遵循這種原則的程式碼在擴展時並不發生改變,因此無需上述的過程。

我們通常在程式設計中利用介面、抽象類、繼承和實現等方式來體現開閉原則。

開閉原則作用

開閉原則是面向對象程式設計的終極目標,它使軟體實體擁有一定的適應性和靈活性的同時具備穩定性和延續性。具體來說,其作用如下

  1. 對軟體測試的影響 軟體遵守開閉原則的話,軟體測試時只需要對擴展的程式碼進行測試就可以了,因為原有的測試程式碼仍然能夠正常運行。
  2. 可以提高程式碼的可復用性 粒度越小,被複用的可能性就越大;在面向對象的程式設計中,根據原子和抽象編程可以提高程式碼的可復用性。
  3. 可以提高軟體的可擴展性和可維護性 遵守開閉原則的軟體,其穩定性高和延續性強,從而易於擴展和維護。

開閉原則案例

1. 描述

我們設計圖書介面、電子書介面、以及SSM電子書類和美食書籍類。電子書介面通過繼承圖書介面,對其進行了擴展,增加了getSize()方法,即獲取電子書記憶體大大小。SSM電子書類通過實現電子書介面進一步擴展,增加了SSMComtent方法。美食書籍類通過實現圖書介面,同樣實現了擴展的方法。

以後如果我們有了更多的武俠類、遊戲類……等書籍,不需要對原來的圖書介面進行修改,只需要繼承完成擴展即可。

2. uml 圖

3. 具體程式碼

圖書介面

import java.util.Date;    /**   * 圖書介面   * 價格、書名、出版日期   */  public interface IBook {      double getPrince();      String getName();      Date publishDate();  }

電子書介面,擴展了一個方法獲取電子書所佔大小的方法。

/**   * 電子書介面   */  public interface IComputerBook extends IBook{      /**       * 獲取電子書大小 16kb       * */      String getSize();  }

實現圖書介面實現擴展。

import java.util.Date;    public class FoodBook implements IBook{        private String name;      private double price;      private Date publishDate;        public FoodBook(String name, double price, Date publishDate) {          this.name = name;          this.price = price;          this.publishDate = publishDate;      }        @Override      public double getPrince() {          return price;      }        @Override      public String getName() {          return name;      }        @Override      public Date publishDate() {          return publishDate;      }        public void foodContent() {          System.out.println("美食書籍: " + name + "-內容豐富哦!僅需要" + price +"元");      }  }

實現電子書介面實現擴展。

import java.util.Date;  public class SSMBook implements IComputerBook {        private String name;      private double price;      private Date publishDate;      private String size;      private String author;        public SSMBook(String name, double price, Date publishDate, String size, String author) {          this.name = name;          this.price = price;          this.publishDate = publishDate;          this.size = size;          this.author = author;      }        @Override      public String getSize() {          return size;      }        @Override      public double getPrince() {          return price;      }        @Override      public String getName() {          return name;      }        @Override      public Date publishDate() {          return publishDate;      }        public void SSMComtent() {          System.out.println("SSM架構實戰書籍:" + name + "-作者:" + author);      }  }

測試類

import java.util.Date;    public class Main {      public static void main(String[] args) {          FoodBook foodBook = new FoodBook("廚房秘籍", 30.00, new Date());          showBookConten(foodBook);            SSMBook ssmBook = new SSMBook("ssm架構", 57.20, new Date(), "20MB", "anben");          showBookConten(ssmBook);      }        private static void showBookConten(IBook iBook) {          if (iBook instanceof IComputerBook) {              SSMBook ssmBook = (SSMBook) iBook;              ssmBook.SSMComtent();          } else {              FoodBook foodBook = (FoodBook) iBook;              foodBook.foodContent();          }      }  }

測試結果