日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

理解軟件設(shè)計模式

 

設(shè)計模式可以幫助消除冗余代碼。學(xué)習(xí)如何利用 JAVA 使用單例模式、工廠模式和觀察者模式。

-- Bryant Son(作者)

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

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

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

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

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

如何遵循本指南

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

必要條件

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

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

安裝好 Git 后運(yùn)行下列命令克隆這個工程:

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

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

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

單例模式:避免每次創(chuàng)建一個對象

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

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

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

下面這幅圖展示了典型的類對象創(chuàng)建過程。當(dāng)客戶端請求創(chuàng)建一個對象時,構(gòu)造函數(shù)會創(chuàng)建或者實例化一個對象并調(diào)用方法返回這個類給調(diào)用者。但是每次請求一個對象都會發(fā)生這樣的情況:構(gòu)造函數(shù)被調(diào)用,一個新的對象被創(chuàng)建并且它返回了一個獨一無二的對象。我猜面向?qū)ο笳Z言的創(chuàng)建者有每次都創(chuàng)建一個新對象的理由,但是單例過程的支持者說這是冗余的且浪費(fèi)資源。

 

理解軟件設(shè)計模式

Normal class instantiation

 

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

 

理解軟件設(shè)計模式

Singleton pattern instantiation

 

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

package org.opensource.demo.singleton;
public class OpensourceSingleton {
 private static OpensourceSingleton uniqueInstance;
 private OpensourceSingleton() {
 }
 public static OpensourceSingleton getInstance() {
 if (uniqueInstance == null) {
 uniqueInstance = new OpensourceSingleton();
 }
 return uniqueInstance;
 }
}

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

Opensource newObject = Opensource.getInstance();

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

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

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

package org.opensource.demo.singleton;
public class ImprovedOpensourceSingleton {
 private volatile static ImprovedOpensourceSingleton uniqueInstance;
 private ImprovedOpensourceSingleton() {}
 public static ImprovedOpensourceSingleton getInstance() {
 if (uniqueInstance == null) {
 synchronized (ImprovedOpensourceSingleton.class) {
 if (uniqueInstance == null) {
 uniqueInstance = new ImprovedOpensourceSingleton();
 }
 }
 }
 return uniqueInstance;
 }
}

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

工廠模式:將對象創(chuàng)建委派給工廠類以隱藏創(chuàng)建邏輯

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

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

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

 

理解軟件設(shè)計模式

Factory pattern

 

客戶端請求工廠類創(chuàng)建類型為 x 的某個對象,而不是客戶端直接調(diào)用對象創(chuàng)建。根據(jù)其類型,工廠模式?jīng)Q定要創(chuàng)建和返回的對象。

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

package org.opensource.demo.factory;
public class OpensourceFactory {
 public OpensourceJVMServers getServerByVendor([String][18] name) {
 if(name.equals("Apache")) {
 return new Tomcat();
 }
 else if(name.equals("Eclipse")) {
 return new Jetty();
 }
 else if (name.equals("RedHat")) {
 return new WildFly();
 }
 else {
 return null;
 }
 }
}

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

package org.opensource.demo.factory;
public interface OpensourceJVMServers {
 public void startServer();
 public void stopServer();
 public [String][18] getName();
}

這是一個 OpensourceJVMServers 類的實現(xiàn)示例。當(dāng) RedHat 被作為類型傳遞給工廠類,WildFly 服務(wù)器將被創(chuàng)建:

package org.opensource.demo.factory;
public class WildFly implements OpensourceJVMServers {
 public void startServer() {
 [System][19].out.println("Starting WildFly Server...");
 }
 public void stopServer() {
 [System][19].out.println("Shutting Down WildFly Server...");
 }
 public [String][18] getName() {
 return "WildFly";
 }
}

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

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

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

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

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

 

理解軟件設(shè)計模式

Observer pattern

 

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

package org.opensource.demo.observer;
public interface Topic {
 public void addObserver([Observer][22] observer);
 public void deleteObserver([Observer][22] observer);
 public void notifyObservers();
}

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

這是一個主題的實現(xiàn)示例:

package org.opensource.demo.observer;
import java.util.List;
import java.util.ArrayList;
public class Conference implements Topic {
 private List<Observer> listObservers;
 private int totalAttendees;
 private int totalSpeakers;
 private [String][18] nameEvent;
 public Conference() {
 listObservers = new ArrayList<Observer>();
 }
 public void addObserver([Observer][22] observer) {
 listObservers.add(observer);
 }
 public void deleteObserver([Observer][22] observer) {
 int i = listObservers.indexOf(observer);
 if (i >= 0) {
 listObservers.remove(i);
 }
 }
 public void notifyObservers() {
 for (int i=0, nObservers = listObservers.size(); i < nObservers; ++ i) {
 [Observer][22] observer = listObservers.get(i);
 observer.update(totalAttendees,totalSpeakers,nameEvent);
 }
 }
 public void setConferenceDetails(int totalAttendees, int totalSpeakers, [String][18] nameEvent) {
 this.totalAttendees = totalAttendees;
 this.totalSpeakers = totalSpeakers;
 this.nameEvent = nameEvent;
 notifyObservers();
 }
}

這段代碼定義了一個特定主題的實現(xiàn)。當(dāng)發(fā)生改變時,這個實現(xiàn)調(diào)用它自己的方法。注意這將獲取觀察者的數(shù)量,它以列表方式存儲,并且可以通知和維護(hù)觀察者。

這是一個觀察者類:

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

這個類定義了一個接口,不同的觀察者可以實現(xiàn)該接口以執(zhí)行特定的操作。

例如,實現(xiàn)了該接口的觀察者可以在會議上打印出與會者和發(fā)言人的數(shù)量:

package org.opensource.demo.observer;
public class MonitorConferenceAttendees implements [Observer][22] {
 private int totalAttendees;
 private int totalSpeakers;
 private [String][18] nameEvent;
 private Topic topic;
 public MonitorConferenceAttendees(Topic topic) {
 this.topic = topic;
 topic.addObserver(this);
 }
 public void update(int totalAttendees, int totalSpeakers, [String][18] nameEvent) {
 this.totalAttendees = totalAttendees;
 this.totalSpeakers = totalSpeakers;
 this.nameEvent = nameEvent;
 printConferenceInfo();
 }
 public void printConferenceInfo() {
 [System][19].out.println(this.nameEvent + " has " + totalSpeakers + " speakers and " + totalAttendees + " attendees");
 }
}

接下來

現(xiàn)在你已經(jīng)閱讀了這篇對于設(shè)計模式的介紹引導(dǎo),你還可以去尋求了解其他設(shè)計模式,例如外觀模式,模版模式和裝飾器模式。也有一些并發(fā)和分布式系統(tǒng)的設(shè)計模式如斷路器模式和錨定模式。

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


via: https://opensource.com/article/19/7/understanding-software-design-patterns

作者: Bryant Son 選題: lujun9972 譯者: arrowfeng 校對: wxy

本文由 LCTT 原創(chuàng)編譯, linux中國 榮譽(yù)推出

分享到:
標(biāo)簽:設(shè)計 軟件
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定