溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java的設(shè)計(jì)模式怎么使用

發(fā)布時(shí)間:2022-01-10 11:00:02 來源:億速云 閱讀:122 作者:iii 欄目:編程語言

本篇內(nèi)容主要講解“Java的設(shè)計(jì)模式怎么使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Java的設(shè)計(jì)模式怎么使用”吧!

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

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

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

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

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

單例模式singleton pattern是非常流行的設(shè)計(jì)模式,它的實(shí)現(xiàn)相對來說很簡單,因?yàn)槟阒恍枰粋€(gè)類。然而,許多開發(fā)人員爭論單例設(shè)計(jì)模式的是否利大于弊,因?yàn)樗狈γ黠@的好處并且容易被濫用。很少有開發(fā)人員直接實(shí)現(xiàn)單例;相反,像 Spring Framework 和 Google Guice 等編程框架內(nèi)置了單例設(shè)計(jì)模式的特性。

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

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

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

Java的設(shè)計(jì)模式怎么使用

Normal class instantiation

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

Java的設(shè)計(jì)模式怎么使用

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();

這段代碼很好的驗(yàn)證了單例模式的思想:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 當(dāng) getInstance() 被調(diào)用時(shí),它通過檢查 null 值來檢查對象是否已經(jīng)被創(chuàng)建。

  3. 如果值為 null,它會(huì)創(chuàng)建一個(gè)新對象并把它保存到私有域,返回這個(gè)對象給調(diào)用者。否則直接返回之前被創(chuàng)建的對象。

單例模式實(shí)現(xiàn)的主要問題是它忽略了并行進(jìn)程。當(dāng)多個(gè)進(jìn)程使用線程同時(shí)訪問資源時(shí),這個(gè)問題就產(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)一下前面的觀點(diǎn),確保只有在你認(rèn)為這是一個(gè)安全的選擇時(shí)才直接實(shí)現(xiàn)你的單例模式。最好的方法是通過使用一個(gè)制作精良的編程框架來利用單例功能。

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

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

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

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

Java的設(shè)計(jì)模式怎么使用

Factory pattern

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

在下列代碼示例中,OpensourceFactory 是工廠類實(shí)現(xiàn),它從調(diào)用者那里獲取類型并根據(jù)該輸入值決定要?jiǎng)?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 是一個(gè) 100% 的抽象類(即接口類),它指示要實(shí)現(xiàn)的是什么,而不是怎樣實(shí)現(xiàn):

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

這是一個(gè) OpensourceJVMServers 類的實(shí)現(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è)的程序員直接實(shí)現(xiàn)觀察者模式。但是,許多消息隊(duì)列和數(shù)據(jù)服務(wù)實(shí)現(xiàn)都借用了觀察者模式的概念。觀察者模式在對象之間定義了一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí),所有依賴它的對象都將被自動(dòng)地通知和更新。

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

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

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

Java的設(shè)計(jì)模式怎么使用

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();}

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

這是一個(gè)主題的實(shí)現(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();    }}

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

這是一個(gè)觀察者類:

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

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

例如,實(shí)現(xiàn)了該接口的觀察者可以在會(huì)議上打印出與會(huì)者和發(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");    }}

到此,相信大家對“Java的設(shè)計(jì)模式怎么使用”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI