日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

开闭原则(开放封闭原则)

發布時間:2023/12/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 开闭原则(开放封闭原则) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

????????一個軟件實體如類、 模塊和函數應該對擴展開放, 對修改關閉。

????????開閉原則的定義已經非常明確地告訴我們:軟件實體應該對擴展開發,對修改關閉,其含義是說一個軟件實體應該通過擴展來實現變化的,而不是通過修改來實現變化的,那什么又是軟件實體?

????????軟件實體包括以下幾個部分:

  • 項目或軟件產品中按照一定的邏輯規則劃分的模塊。
  • 抽象和類。
  • 方法。

????????一個軟件的存在,都會發生變化的,既然變化是一個不變的事實,我們就應該在設計時盡量適應這些變化,從而提高項目的穩定性和靈活性,真正實現“擁抱變化”。開閉原則告訴我們應盡量通過擴展軟件實體的行為來實現變化, 而不是通過修改已有的代碼來完成變化, 它是為軟件實體的未來事件而制定的對現行開發設計進行約束的一個原則。 我們舉例說明什么是開閉原則, 以書店銷售書籍為例,如圖1-1所示。

圖1-1

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 不明白的這個圖畫的意思,可以看一下這個文章?:文章

????????IBook定義了數據的三個屬性: 名稱、 價格和作者。 小說類NovelBook是一個具體的實現
類, 是所有小說書籍的總稱, BookStore指的是書店, IBook接口如代碼清單2-1所示。

//代碼清單2-1 書籍接口 public interface IBook {//書籍有名稱public String getName();//書籍有售價public int getPrice();//書籍有作者public String getAuthor(); }

????????目前書店只出售小說類書籍, 小說類如代碼清單2-2所示。

//代碼清單2-2 小說類。 public class NovelBook implements IBook {//書籍名稱private String name;//書籍的價格private int price;//書籍的作者private String author;//通過構造函數傳遞書籍數據public NovelBook(String _name,int _price,String _author){this.name = _name;this.price = _price;this.author = _author;}//獲得作者是誰public String getAuthor() {return this.author;}//書籍叫什么名字public String getName() {return this.name;}//獲得書籍的價格public int getPrice() {return this.price;} }

????????書店售書的過程如代碼清單2-3所示。

????????注意 我們把價格定義為int類型并不是錯誤, 在非金融類項目中對貨幣處理時, 一般取
2位精度, 通常的設計方法是在運算過程中擴大100倍, 在需要展示時再縮小100倍, 減少精
度帶來的誤差。

//代碼清單2-3所示 public class BookStore {private final static ArrayList<IBook> bookList = new ArrayList<IBook>();//static靜態模塊初始化數據, 實際項目中一般是由持久層完成static{bookList.add(new NovelBook("天龍八部",3200,"金庸"));bookList.add(new NovelBook("巴黎圣母院",5600,"雨果"));bookList.add(new NovelBook("悲慘世界",3500,"雨果"));bookList.add(new NovelBook("金瓶梅",4300,"蘭陵笑笑生"));}//模擬書店買書public static void main(String[] args) {NumberFormat formatter = NumberFormat.getCurrencyInstance();formatter.setMaximumFractionDigits(2);System.out.println("-----------書店賣出去的書籍記錄如下: -----------");for(IBook book:bookList){System.out.println("書籍名稱: " + book.getName()+"\t書籍作者: "book.getAuthor()+"\t書籍價格: "+ formatter.format(book.getPrice()/100.0)+"元");}}}

????????在BookStore中聲明了一個靜態模塊, 實現了數據的初始化,運行結果如下:

-----------------書店賣出去的書籍記錄如下: -------------- 書籍名稱: 天龍八部 書籍作者: 金庸 書籍價格: ¥32.00元 書籍名稱: 巴黎圣母院 書籍作者: 雨果 書籍價格: ¥56.00元 書籍名稱: 悲慘世界 書籍作者: 雨果 書籍價格: ¥35.00元 書籍名稱: 金瓶梅 書籍作者: 蘭陵笑笑生 書籍價格: ¥43.00元

? ? ? ? 現在項目已經完成了,這個時候,產品經理提出:所有40元以上的書籍9折銷售, 其他的8
折銷售。 對已經投產的項目來說, 這就是一個變化,那我們如何對應這次變化,有三種方法可以已經這個問題:

  • 修改接口:

????????在IBook上新增加一個方法getOffPrice(), 專門用于進行打折處理, 所有的實現類實現該方法。 但是這樣修改的后果就是, 實現類NovelBook要修改, BookStore中的main方法也修改, 同時IBook作為接口應該是穩定且可靠的, 不應該經常發生變化, 否則接口作為契約的作用就失去了效能。 因此, 該方案肯定不行的。

  • 修改實現類:

????????修改NovelBook類中的方法, 直接在getPrice()中實現打折處理,或者通過動態替換class文件的方式來完成,顯然也是可以實現的,但是這個方案有個比較明顯的錯誤,例如我們修改這個getPrice()這個方法,那么這個書籍的原價格我們就看不到了,這個方案也是行不通的。

  • 通過擴展實現變化

????????增加一個子類OffNovelBook, 覆寫getPrice方法,修改高層次的模塊(就是static靜態模塊初始化數據)通過OffNovelBook類產生新的對象,就可以完成這次打折的功能,并沒有修改接口,或者修改原有的類,? static靜態模塊該部分屬于高層次的模塊, 是由持久層產生的, 在業務規則改變的情況下高層模塊必須有部分改變以適應新業務, 改變要盡量地少, 防止變化風險的擴散。

圖1-2,擴展后的書店售書類圖

?

????????????????OffNovelBook類繼承了NovelBook, 并覆寫了getPrice方法, 不修改原有的代碼。 新增加的子類OffNovelBook如代碼清單2-4所示。

//代碼清單2-4所示 public class OffNovelBook extends NovelBook {public OffNovelBook(String _name,int _price,String _author){super(_name,_price,_author);}//覆寫銷售價格@Overridepublic int getPrice(){//原價int selfPrice = super.getPrice();int offPrice=0;if(selfPrice>4000){ //原價大于40元, 則打9折offPrice = selfPrice * 90 /100;}else{offPrice = selfPrice * 80 /100;}return offPrice;} }

????????很簡單, 僅僅覆寫了getPrice方法, 通過擴展完成了新增加的業務。 書店類BookStore需
要依賴子類, 代碼稍作修改, 如代碼清單2-5所示。

//代碼清單2-5所示 public class BookStore {private final static ArrayList<IBook> bookList = new ArrayList<IBook>();//static靜態模塊初始化數據, 實際項目中一般是由持久層完成static{bookList.add(new OffNovelBook("天龍八部",3200,"金庸"));bookList.add(new OffNovelBook("巴黎圣母院",5600,"雨果"));bookList.add(new OffNovelBook("悲慘世界",3500,"雨果"));bookList.add(new OffNovelBook("金瓶梅",4300,"蘭陵笑笑生"));}//模擬書店買書public static void main(String[] args) {NumberFormat formatter = NumberFormat.getCurrencyInstance();formatter.setMaximumFractionDigits(2);System.out.println("-----------書店賣出去的書籍記錄如下: -----------");for(IBook book:bookList){System.out.println("書籍名稱: " + book.getName()+"\t書籍作者: "book.getAuthor()+"\t書籍價格: "+ formatter.format(book.getPrice()/100.0)+"元");}} }

? ? ? ? ?我們只是修改了static靜態模塊,其他的地方沒有動.

-----------------書店賣出去的書籍記錄如下: -------------- 書籍名稱: 天龍八部 書籍作者: 金庸 書籍價格: ¥25.60元 書籍名稱: 巴黎圣母院 書籍作者: 雨果 書籍價格: ¥50.40元 書籍名稱: 悲慘世界 書籍作者: 雨果 書籍價格: ¥28.00元 書籍名稱: 金瓶梅 書籍作者: 蘭陵笑笑生 書籍價格: ¥38.70元

????????OK,

參考文檔來自:設計模式之禪。
?

總結

以上是生活随笔為你收集整理的开闭原则(开放封闭原则)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。