成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

理解軟件設計模式

開發 后端
設計模式可以幫助消除冗余代碼。學習如何利用 Java 使用單例模式、工廠模式和觀察者模式。

 [[273480]]

設計模式可以幫助消除冗余代碼。學習如何利用 Java 使用單例模式、工廠模式和觀察者模式。

如果你是一名正在致力于計算機科學或者相關學科的程序員或者學生,很快,你將會遇到一條術語 “軟件設計模式software design pattern”。根據維基百科,“軟件設計模式是在平常的軟件設計工作中所遭遇的問題的一種通用的、可重復使用的解決方案”。我對該定義的理解是:當在從事于一個編碼項目時,你經常會思考,“嗯,這里貌似是冗余代碼,我覺得是否能改變這些代碼使之更靈活和便于修改?”因此,你會開始考慮怎樣分割那些保持不變的內容和需要經常改變的內容。

設計模式是一種通過分割那些保持不變的部分和經常變化的部分,讓你的代碼更容易修改的方法。

不出意外的話,每個從事編程項目的人都可能會有同樣的思考。特別是那些工業級別的項目,在那里通常工作著數十甚至數百名開發者;協作過程表明必須有一些標準和規則來使代碼更加優雅并適應變化。這就是為什么我們有了 面向對象編程(OOP)和 軟件框架工具。設計模式有點類似于 OOP,但它通過將變化視為自然開發過程的一部分而進一步發展。基本上,設計模式利用了一些 OOP 的思想,比如抽象和接口,但是專注于改變的過程。

當你開始開發項目時,你經常會聽到這樣一個術語重構,它意味著通過改變代碼使它變得更優雅和可復用;這就是設計模式耀眼的地方。當你處理現有代碼時(無論是由其他人構建還是你自己過去構建的),了解設計模式可以幫助你以不同的方式看待事物,你將發現問題以及改進代碼的方法。

有很多種設計模式,其中單例模式、工廠模式和觀察者模式三種最受歡迎,在這篇文章中我將會一一介紹它們。

如何遵循本指南

無論你是一位有經驗的編程工作者還是一名剛剛接觸的新手,我想讓這篇教程讓每個人都很容易理解。設計模式概念并不容易理解,減少開始旅程時的學習曲線始終是首要任務。因此,除了這篇帶有圖表和代碼片段的文章外,我還創建了一個 GitHub 倉庫,你可以克隆倉庫并在你的電腦上運行這些代碼來實現這三種設計模式。你也可以觀看我創建的 YouTube視頻

必要條件

如果你只是想了解一般的設計模式思想,則無需克隆示例項目或安裝任何工具。但是,如果要運行示例代碼,你需要安裝以下工具:

  • Java 開發套件(JDK):我強烈建議使用 OpenJDK
  • Apache Maven:這個簡單的項目使用 Apache Maven 構建;好的是許多 IDE 自帶了Maven。
  • 交互式開發編輯器(IDE):我使用 社區版 IntelliJ,但是你也可以使用 Eclipse IDE 或者其他你喜歡的 Java IDE。
  • Git:如果你想克隆這個工程,你需要 Git 客戶端。

安裝好 Git 后運行下列命令克隆這個工程:

  1. git clone https://github.com/bryantson/OpensourceDotComDemos.git

然后在你喜歡的 IDE 中,你可以將 TopDesignPatterns 倉庫中的代碼作為 Apache Maven 項目導入。

我使用的是 Java,但你也可以使用支持抽象原則的任何編程語言來實現設計模式。

單例模式:避免每次創建一個對象

單例模式singleton pattern是非常流行的設計模式,它的實現相對來說很簡單,因為你只需要一個類。然而,許多開發人員爭論單例設計模式的是否利大于弊,因為它缺乏明顯的好處并且容易被濫用。很少有開發人員直接實現單例;相反,像 Spring Framework 和 Google Guice 等編程框架內置了單例設計模式的特性。

但是了解單例模式仍然有巨大的用處。單例模式確保一個類僅創建一次且提供了一個對它的全局訪問點。

單例模式:確保僅創建一個實例且避免在同一個項目中創建多個實例。

下面這幅圖展示了典型的類對象創建過程。當客戶端請求創建一個對象時,構造函數會創建或者實例化一個對象并調用方法返回這個類給調用者。但是每次請求一個對象都會發生這樣的情況:構造函數被調用,一個新的對象被創建并且它返回了一個獨一無二的對象。我猜面向對象語言的創建者有每次都創建一個新對象的理由,但是單例過程的支持者說這是冗余的且浪費資源。

Normal class instantiation

Normal class instantiation

下面這幅圖使用單例模式創建對象。這里,構造函數僅當對象首次通過調用預先設計好的 getInstance() 方法時才會被調用。這通常通過檢查該值是否為 null 來完成,并且這個對象被作為私有變量保存在單例類的內部。下次 getInstance() 被調用時,這個類會返回第一次被創建的對象。而沒有新的對象產生;它只是返回舊的那一個。

Singleton pattern instantiation

Singleton pattern instantiation

下面這段代碼展示了創建單例模式最簡單的方法:

  1. package org.opensource.demo.singleton;
  2.  
  3. public class OpensourceSingleton {
  4.  
  5.     private static OpensourceSingleton uniqueInstance;
  6.  
  7.     private OpensourceSingleton() {
  8.     }
  9.  
  10.     public static OpensourceSingleton getInstance() {
  11.         if (uniqueInstance == null) {
  12.             uniqueInstance = new OpensourceSingleton();
  13.         }
  14.         return uniqueInstance;
  15.     }
  16.  
  17. }

在調用方,這里展示了如何調用單例類來獲取對象:

  1. Opensource newObject = Opensource.getInstance();

這段代碼很好的驗證了單例模式的思想:

  1. 當 getInstance() 被調用時,它通過檢查 null 值來檢查對象是否已經被創建。
  2. 如果值為 null,它會創建一個新對象并把它保存到私有域,返回這個對象給調用者。否則直接返回之前被創建的對象。

單例模式實現的主要問題是它忽略了并行進程。當多個進程使用線程同時訪問資源時,這個問題就產生了。對于這種情況有對應的解決方案,它被稱為雙重檢查鎖,用于多線程安全,如下所示:

  1. package org.opensource.demo.singleton;
  2.  
  3. public class ImprovedOpensourceSingleton {
  4.  
  5.     private volatile static ImprovedOpensourceSingleton uniqueInstance;
  6.  
  7.     private ImprovedOpensourceSingleton() {}
  8.  
  9.     public static ImprovedOpensourceSingleton getInstance() {
  10.         if (uniqueInstance == null) {
  11.             synchronized (ImprovedOpensourceSingleton.class) {
  12.                 if (uniqueInstance == null) {
  13.                     uniqueInstance = new ImprovedOpensourceSingleton();
  14.                 }
  15.             }
  16.         }
  17.         return uniqueInstance;
  18.     }
  19.  
  20. }

再強調一下前面的觀點,確保只有在你認為這是一個安全的選擇時才直接實現你的單例模式。最好的方法是通過使用一個制作精良的編程框架來利用單例功能。

工廠模式:將對象創建委派給工廠類以隱藏創建邏輯

工廠模式factory pattern是另一種眾所周知的設計模式,但是有一小點復雜。實現工廠模式的方法有很多,而下列的代碼示例為最簡單的實現方式。為了創建對象,工廠模式定義了一個接口,讓它的子類去決定實例化哪一個類。

工廠模式:將對象創建委派給工廠類,因此它能隱藏創建邏輯。

下列的圖片展示了最簡單的工廠模式是如何實現的。

Factory pattern

Factory pattern

客戶端請求工廠類創建類型為 x 的某個對象,而不是客戶端直接調用對象創建。根據其類型,工廠模式決定要創建和返回的對象。

在下列代碼示例中,OpensourceFactory 是工廠類實現,它從調用者那里獲取類型并根據該輸入值決定要創建和返回的對象:

  1. package org.opensource.demo.factory;
  2.  
  3. public class OpensourceFactory {
  4.  
  5.     public OpensourceJVMServers getServerByVendor([String][18] name) {
  6.         if(name.equals("Apache")) {
  7.             return new Tomcat();
  8.         }
  9.         else if(name.equals("Eclipse")) {
  10.             return new Jetty();
  11.         }
  12.         else if (name.equals("RedHat")) {
  13.             return new WildFly();
  14.         }
  15.         else {
  16.             return null;
  17.         }
  18.     }
  19. }

OpenSourceJVMServer 是一個 100% 的抽象類(即接口類),它指示要實現的是什么,而不是怎樣實現:

  1. package org.opensource.demo.factory;
  2.  
  3. public interface OpensourceJVMServers {
  4.     public void startServer();
  5.     public void stopServer();
  6.     public [String][18] getName();
  7. }

這是一個 OpensourceJVMServers 類的實現示例。當 RedHat 被作為類型傳遞給工廠類,WildFly 服務器將被創建:

  1. package org.opensource.demo.factory;
  2.  
  3. public class WildFly implements OpensourceJVMServers {
  4.     public void startServer() {
  5.         [System][19].out.println("Starting WildFly Server...");
  6.     }
  7.  
  8.     public void stopServer() {
  9.         [System][19].out.println("Shutting Down WildFly Server...");
  10.     }
  11.  
  12.     public [String][18] getName() {
  13.         return "WildFly";
  14.     }
  15. }

觀察者模式:訂閱主題并獲取相關更新的通知

最后是觀察者模式observer pattern。像單例模式那樣,很少有專業的程序員直接實現觀察者模式。但是,許多消息隊列和數據服務實現都借用了觀察者模式的概念。觀察者模式在對象之間定義了一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴它的對象都將被自動地通知和更新。

觀察者模式:如果有更新,那么訂閱了該話題/主題的客戶端將被通知。

理解觀察者模式的最簡單方法是想象一個郵件列表,你可以在其中訂閱任何主題,無論是開源、技術、名人、烹飪還是您感興趣的任何其他內容。每個主題維護者一個它的訂閱者列表,在觀察者模式中它們相當于觀察者。當某一個主題更新時,它所有的訂閱者(觀察者)都將被通知這次改變。并且訂閱者總是能取消某一個主題的訂閱。

如下圖所示,客戶端可以訂閱不同的主題并添加觀察者以獲得最新信息的通知。因為觀察者不斷的監聽著這個主題,這個觀察者會通知客戶端任何發生的改變。

Observer pattern

Observer pattern

讓我們來看看觀察者模式的代碼示例,從主題/話題類開始:

  1. package org.opensource.demo.observer;
  2.  
  3. public interface Topic {
  4.  
  5.     public void addObserver([Observer][22] observer);
  6.     public void deleteObserver([Observer][22] observer);
  7.     public void notifyObservers();
  8. }

這段代碼描述了一個為不同的主題去實現已定義方法的接口。注意一個觀察者如何被添加、移除和通知的。

這是一個主題的實現示例:

  1. package org.opensource.demo.observer;
  2.  
  3. import java.util.List;
  4. import java.util.ArrayList;
  5.  
  6. public class Conference implements Topic {
  7.     private List<Observer> listObservers;
  8.     private int totalAttendees;
  9.     private int totalSpeakers;
  10.     private [String][18] nameEvent;
  11.  
  12.     public Conference() {
  13.         listObservers = new ArrayList<Observer>();
  14.     }
  15.  
  16.     public void addObserver([Observer][22] observer) {
  17.         listObservers.add(observer);
  18.     }
  19.  
  20.     public void deleteObserver([Observer][22] observer) {
  21.         int i = listObservers.indexOf(observer);
  22.         if (i >= 0) {
  23.             listObservers.remove(i);
  24.         }
  25.     }
  26.  
  27.     public void notifyObservers() {
  28.         for (int i=0, nObservers = listObservers.size(); i < nObservers; ++ i) {
  29.             [Observer][22] observer = listObservers.get(i);
  30.             observer.update(totalAttendees,totalSpeakers,nameEvent);
  31.         }
  32.     }
  33.  
  34.     public void setConferenceDetails(int totalAttendees, int totalSpeakers, [String][18] nameEvent) {
  35.         this.totalAttendees = totalAttendees;
  36.         this.totalSpeakers = totalSpeakers;
  37.         this.nameEvent = nameEvent;
  38.         notifyObservers();
  39.     }
  40. }

這段代碼定義了一個特定主題的實現。當發生改變時,這個實現調用它自己的方法。注意這將獲取觀察者的數量,它以列表方式存儲,并且可以通知和維護觀察者。

這是一個觀察者類:

  1. package org.opensource.demo.observer;
  2.  
  3. public interface [Observer][22] {
  4.     public void update(int totalAttendees, int totalSpeakers, [String][18] nameEvent);
  5. }

這個類定義了一個接口,不同的觀察者可以實現該接口以執行特定的操作。

例如,實現了該接口的觀察者可以在會議上打印出與會者和發言人的數量:

  1. package org.opensource.demo.observer;
  2.  
  3. public class MonitorConferenceAttendees implements [Observer][22] {
  4.     private int totalAttendees;
  5.     private int totalSpeakers;
  6.     private [String][18] nameEvent;
  7.     private Topic topic;
  8.  
  9.     public MonitorConferenceAttendees(Topic topic) {
  10.         this.topic = topic;
  11.         topic.addObserver(this);
  12.     }
  13.  
  14.     public void update(int totalAttendees, int totalSpeakers, [String][18] nameEvent) {
  15.         this.totalAttendees = totalAttendees;
  16.         this.totalSpeakers = totalSpeakers;
  17.         this.nameEvent = nameEvent;
  18.         printConferenceInfo();
  19.     }
  20.  
  21.     public void printConferenceInfo() {
  22.         [System][19].out.println(this.nameEvent + " has " + totalSpeakers + " speakers and " + totalAttendees + " attendees");
  23.     }
  24. }

接下來

現在你已經閱讀了這篇對于設計模式的介紹引導,你還可以去尋求了解其他設計模式,例如外觀模式,模版模式和裝飾器模式。也有一些并發和分布式系統的設計模式如斷路器模式和錨定模式。

可是,我相信最好的磨礪你的技能的方式首先是通過在你的業余項目或者練習中實現這些設計模式。你甚至可以開始考慮如何在實際項目中應用這些設計模式。接下來,我強烈建議你查看 OOP 的 SOLID 原則。之后,你就準備好了解其他設計模式。 

責任編輯:龐桂玉 來源: Linux中國
相關推薦

2011-07-14 14:46:46

設計模式

2010-08-11 09:15:07

設計模式Python

2023-10-19 13:43:00

設計模式軟件設計

2011-07-21 14:33:02

設計模式

2013-06-07 11:31:36

面向對象設計模式

2013-05-08 09:12:44

2022-09-19 06:25:14

設計模式GoF

2017-08-28 15:00:20

軟件系統架構風格

2022-02-16 07:32:10

性能代碼編程

2010-12-27 10:03:29

軟件設計師

2012-12-25 09:38:41

JavaScript設計模式

2023-10-20 13:21:55

軟件設計模式架構

2014-04-30 12:18:07

軟件設計

2010-06-24 14:39:09

HART協議

2021-11-23 20:41:05

對象軟件設計

2012-06-07 10:45:12

軟件架構設計原則

2012-04-12 09:38:21

JavaScript

2022-06-08 10:10:00

軟件設計設計文檔需求設計

2012-05-09 12:35:48

美國YPiPad軟件

2012-06-07 10:17:55

軟件設計設計原則Java
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: av在线一区二区三区 | 欧美一级二级在线观看 | 久久精品国产免费一区二区三区 | 久久综合一区 | 久草院线| 一a级片 | 曰批视频在线观看 | 国产精品女人久久久 | 欧美 日韩 国产 成人 | 国产精品美女久久久久久免费 | 中文字幕欧美日韩一区 | 亚洲综合国产精品 | www.av在线| 国产在线精品免费 | 精品一区二区三区在线播放 | 日韩欧美二区 | 午夜精品一区二区三区免费视频 | 精品国产aⅴ | 日韩在线免费视频 | 欧美一区二区在线播放 | av网站免费在线观看 | 欧美日韩欧美 | 久久久亚洲一区 | 99久热| 91精品国产乱码久久久久久久 | 99久久久久久 | 欧美成人一区二免费视频软件 | 亚洲视频免费在线观看 | 欧美一区中文字幕 | 国产一区二区毛片 | jav成人av免费播放 | 国产一区二区在线视频 | 国外成人免费视频 | 日韩毛片免费视频 | 国产精彩视频一区 | 国产欧美一区二区三区久久 | 国产丝袜一区二区三区免费视频 | 国产精品欧美一区二区三区 | 久久三级av | 久久机热| 欧美在线a |