linux做網(wǎng)站服務(wù)器那個軟件好品牌策劃方案模板
個人主頁: danci_ ?
🔥系列專欄:《設(shè)計模式》《MYSQL應(yīng)用》
💪🏻 制定明確可量化的目標(biāo),堅持默默的做事。
🚀 轉(zhuǎn)載自熱榜文章:探索設(shè)計模式的魅力:簡單工廠模式
簡單工廠模式(Simple Factory Pattern)是一種創(chuàng)建型設(shè)計模式,其主要目的是用于創(chuàng)建對象的實例。這種模式通過封裝創(chuàng)建對象的代碼來降低客戶代碼與具體類之間的耦合度。簡單工廠不是GoF(四人幫)設(shè)計模式之一,但它是一個常用的編程慣用法。
在簡單工廠模式中,創(chuàng)建對象的責(zé)任通常由一個單一的工廠類承擔(dān),這個工廠類有一個用來根據(jù)輸入?yún)?shù)創(chuàng)建并返回不同類型對象實例的方法。這種模式通常用于管理和創(chuàng)建那些具有共同接口或父類的一組類的實例。
目錄
一、業(yè)務(wù)案例
二、簡單實現(xiàn)
三、簡單工廠模式
3.1 面向?qū)ο缶幊?/p>
3.1.2 接口
3.1.2 面向接口編程
3.2?不用設(shè)計模式解決
3.3?用簡單工廠模式解決
3.3.1 工廠模式結(jié)構(gòu)及說明
3.3.2 模式分解
3.3.3 理解簡單工廠模式
3.4 簡單工廠模式優(yōu)缺點
3.5 思考簡單工廠模式
3.5.1 本質(zhì)
3.5.2 何時選用簡單工廠模式
3.6 相關(guān)設(shè)計模式結(jié)合
一、業(yè)務(wù)案例
請用程序?qū)崿F(xiàn)輸入兩個整數(shù)和運算符,然后輸出結(jié)果。
二、簡單實現(xiàn)
? ? 兩三下就搞定,代碼如下:
import java.util.Scanner;public class Tester {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int a = scanner.nextInt();int b = scanner.nextInt();String c = scanner.nextLine().trim();scanner.close();switch (c) {case "+": {System.out.println(a + b);return;}case "-": {System.out.println(a - b);return;}case "*": {System.out.println(a * b);return;}case "/": {if (b == 0) {return;}System.out.println(a / b);return;}default: return;}}
}
正常運行看結(jié)果看似沒有什么毛病,但閱讀一下代碼就實在不康入目
- 看不懂變量abc代碼什么意思。
- 好多判斷。
- 如果第一次和第二次輸入符號會出錯 等等。
把以上問題全部解決就行了么?當(dāng)然不行,Java是面向?qū)ο缶幊獭?/u>
????????
三、簡單工廠模式
3.1 面向?qū)ο缶幊?/h3>
? ? 面向?qū)ο缶幊淌且环N基于對象和類的編程方法,它將數(shù)據(jù)和操作數(shù)據(jù)的方法封裝在一起,以創(chuàng)建對象。在Java中,你可以通過類、對象、封裝、繼承和多態(tài)來構(gòu)建復(fù)雜的軟件系統(tǒng)。這些概念使得代碼更具可維護(hù)性、可重用性和擴(kuò)展性,是Java編程語言的重要特征之一。
3.1.2 接口
Java中的接口是一種抽象數(shù)據(jù)類型,它定義了一組方法的規(guī)范,但沒有提供方法的具體實現(xiàn)。接口可以被類實現(xiàn),一個類可以實現(xiàn)一個或多個接口。
在Java中,通過使用
interface
關(guān)鍵字來聲明接口。接口的方法默認(rèn)是public
和abstract
的,也就是說,接口中的方法必須是公共的和抽象的,不需要顯式地聲明這兩個修飾符。
????????
接口可以包含以下類型的成員:
- 抽象方法:接口中的方法沒有方法體,只有方法簽名。
- 默認(rèn)方法:在Java 8中引入的,默認(rèn)方法在接口中有一個具體的實現(xiàn)。實現(xiàn)類可以直接繼承默認(rèn)方法,也可以選擇覆蓋它們。
- 靜態(tài)方法:在Java 8中引入的,接口中的靜態(tài)方法可以通過接口名稱直接調(diào)用,無需通過實現(xiàn)類。
- 常量:接口中可以定義常量,它們默認(rèn)是
public
、static
和final
的。
接口的主要作用是實現(xiàn)多繼承或多重實現(xiàn)。通過實現(xiàn)接口,一個類可以同時擁有多個接口定義的行為,并且可以在不同的類之間共享和重用代碼。一個類可以實現(xiàn)多個接口,但只能繼承一個類。
????????
3.1.2 面向接口編程
Java面向接口編程是一種編程思想和重要的原則,它強(qiáng)調(diào)程序設(shè)計應(yīng)該以接口為基礎(chǔ)進(jìn)行。這種編程方式的關(guān)鍵思想是將接口作為代碼組織和交互的核心,而不是將具體的實現(xiàn)細(xì)節(jié)暴露給調(diào)用者。
在面向接口編程中,接口是一種契約,它定義了一組方法的規(guī)范。類可以實現(xiàn)接口,以表明它們能夠提供接口中定義的行為。通過使用接口,可以減少代碼之間的耦合性,并提高代碼的可讀性、可維護(hù)性和可擴(kuò)展性。? ? ??
面向接口編程的優(yōu)點包括:
- 擴(kuò)展性:通過定義接口,可以方便地添加新的實現(xiàn)類,從而提供更多的功能擴(kuò)展點。
- 可替換性:由于面向接口編程的關(guān)注點是接口而不是具體實現(xiàn),所以可以方便地替換實現(xiàn)類,以滿足不同的需求和場景。
- 可測試性:接口的抽象性使得可以更容易地對代碼的不同部分進(jìn)行單元測試和模擬。
- 代碼復(fù)用性:通過多個類實現(xiàn)同一個接口,可以實現(xiàn)代碼邏輯的復(fù)用。
- 降低耦合性:通過依賴于接口而不是具體的實現(xiàn)類,可以降低代碼之間的耦合性,提高系統(tǒng)的靈活性和可維護(hù)性。
在實踐中,面向接口編程可以結(jié)合工廠模式來進(jìn)一步提高代碼的可擴(kuò)展性和靈活性。在Java 程序設(shè)計里面,非常講究層的劃分和模塊的劃分,每層之間只通過接口來通信,而不需要知道具體的實現(xiàn)。
總的來說,接口提供了一種規(guī)范和契約的機(jī)制,用于定義類應(yīng)該實現(xiàn)的方法,以及類們之間的協(xié)議。
????????????????
3.2?不用設(shè)計模式解決
結(jié)構(gòu)圖如下
代碼實現(xiàn)如下:
(接口)
/*** 運算接口 <br/>** @author danci_* @date 2024/1/13 11:13:00*/
public interface CalApi {/*** 根據(jù)傳入的兩個數(shù)字和運算符獲得運算結(jié)果** @param number1 數(shù)字1* @param number2 數(shù)字2* @param operator 運算符* @return*/int cal(int number1, int number2, String operator);
}
(實現(xiàn)類)
/*** 運算實現(xiàn)類 <br/>** @author danci_* @date 2024/1/13 11:14:46*/
public class CalApiImpl implements CalApi {@Overridepublic int cal(int number1, int number2, String operator) {switch (operator) {case "+": {return number1 + number2;}case "-": {return number1 - number2;}case "*": {return number1 * number2;}case "/": {if (number2 == 0) {return 0;}return number1 / number2;}default: return 0;} }
}
(客戶端實現(xiàn))
public class Client {public static void main(String[] args) {CalApi calApi = new CalApiImpl();calApi.cal(1, 2, "+");}
}
問題
? ? 客戶的這行代碼?CalApi calApi = new CalApiImpl(),客戶端不僅知道了接口還知道了接口具體的實現(xiàn),違背面向接口編程的思想。
? ? 使用工廠模式來解決問題。
????????
3.3?用簡單工廠模式解決
定義?個創(chuàng)建對象的接口,讓其子類?己決定實例化哪?個工廠類,?廠模式使其創(chuàng)建過程延遲到?子類進(jìn)?。
解決思路
? ? 客戶端不應(yīng)該知道具體的實現(xiàn)類,只知道接口又不應(yīng)該知道具體的實現(xiàn)來滿足業(yè)務(wù),該怎么辦?而創(chuàng)建接口又是需要知道實現(xiàn)類的。
? ??創(chuàng)建一個工廠類,由工廠類來實例化接口,對外提供能獲取接口的實例對象,然后就可以操作接口的方法了。
? ? 客戶端通過工廠類來獲取接口對象來調(diào)接口對應(yīng)的方法。如此,實現(xiàn)了客戶端不需要知道具體的接口實現(xiàn)了。
????????
3.3.1 工廠模式結(jié)構(gòu)及說明
- Api:定義客戶所需要的功能接口。
-
Impl:具體實現(xiàn)Api 的實現(xiàn)類,可能會有多個。
-
Fact ory: 工廠,選擇合適的實現(xiàn) 類來創(chuàng)建Api 接又對象。
-
Client:客戶端,通過Factory 來獲取Api接又對象,然后面向Api接又編程。
代碼實現(xiàn)如下:
? 定義接口,代碼如下:
public interface CalApi {/*** 根據(jù)傳入的兩個數(shù)字進(jìn)行運算** @param number1 數(shù)字1* @param number2 數(shù)字2* @return*/int cal(int number1, int number2);
}
?????????
? 運算實現(xiàn)類,代碼如下:
public class AdditionCalApi implements CalApi {/*** 獲取數(shù)字number1 + 數(shù)字number2的結(jié)果* * @param number1 數(shù)字1* @param number2 數(shù)字2* @return int 加法運算結(jié)果*/@Overridepublic int cal(int number1, int number2) {return number1 + number2;}
}
public class SubtractionCalApi implements CalApi {/*** 獲取數(shù)字number1 - 數(shù)字number2的結(jié)果** @param number1 數(shù)字1* @param number2 數(shù)字2* @return*/@Overridepublic int cal(int number1, int number2) {return number1 - number2;}
}
????????
? 創(chuàng)建工廠類,代碼如下:
public class Factory {public static CalApi getCalApi(String operator) {switch (operator) {case "+": {return new AdditionCalApi();}case "-": {return new SubtractionCalApi();}default: return null;}}
}
????????
? 客戶端如何使用工廠?客戶端就不用再自己去創(chuàng)建接口的對象了,應(yīng)該使用工廠來獲取 。 經(jīng)過改造,客戶端代碼如下:
public class Client {public static void main(String[] args) {CalApi calApi1 = Factory.getCalApi("+");int rs1 = calApi1.cal(12, 55);System.out.println(rs1);CalApi calApi2 = Factory.getCalApi("-");int rs2 = calApi2.cal(12, 55);System.out.println(rs2);}
}
? ? 客戶端通過簡單工廠創(chuàng)建 了一個實現(xiàn)接口的對象,然后面向接口編程,從客戶端來看,它根本不知道具體的實現(xiàn)是什么,也不知道是如何實現(xiàn)的,它只知道通過工廠獲得了一個接口對象 , 然后通過這個接口來獲取想要的功能。
????????
3.3.2 模式分解
- 客戶端與接口具體的實現(xiàn)類實現(xiàn)了完全的解藕。
- 工廠類跟接口和接口的實現(xiàn)在一起的,是一個封裝體。(如下圖)
? ??圖3?中的虛線框,就好比是一個組件的包裝邊界,表示接口、實現(xiàn)類和工廠類組合成了一 個組件。在這個封裝體里面,只有接口和工廠是對外的,也就是讓外部知道并使用的 ,所以故意漏了一些在虛線框外,而具體的實現(xiàn)類是不對外的,被完全包含在虛線框內(nèi)。
? ??對于客戶端而言,只是知道了接口Api和簡單工廠Factory,通過Factory 就可以獲得Api 了,這樣就達(dá)到了讓Client在不知道具體實現(xiàn)類的情況下獲取接口Api。 所以看似簡單地將new Impl (這句話從客戶端里面移動到了簡單工廠里面,其實是有了質(zhì)的變化的。
????????
3.3.3 理解簡單工廠模式
簡單工廠模式(Simple Factory Pattern)屬于創(chuàng)建型設(shè)計模式之一,其核心思想是通過一個專門的工廠類來負(fù)責(zé)創(chuàng)建其他類的實例,將實例的創(chuàng)建與使用解耦,減少客戶端直接創(chuàng)建對象的責(zé)任。
? 簡單工廠模式通常涉及以下三個角色:
-
工廠角色(Factory):這是簡單工廠模式的核心,含有一個創(chuàng)建產(chǎn)品的方法,客戶端調(diào)用這個方法來請求產(chǎn)品。根據(jù)傳入的參數(shù),工廠決定創(chuàng)建哪一種產(chǎn)品。
-
抽象產(chǎn)品角色(Product):這是工廠需要創(chuàng)建的所有對象的父類或接口,通常是一個抽象類或接口,定義了產(chǎn)品的公共接口。
-
具體產(chǎn)品角色(Concrete Product):工廠方法創(chuàng)建的具體實例,這些產(chǎn)品是繼承自抽象產(chǎn)品或?qū)崿F(xiàn)了產(chǎn)品接口的類。
? 簡單工廠模式的核心思想可以概括為:
-
集中管理:將對象的創(chuàng)建集中到一個位置,便于管理和維護(hù)。
-
解耦:減少系統(tǒng)中的代碼耦合,使用者不需要知道具體的產(chǎn)品類名,只需要知道工廠類和產(chǎn)品的抽象接口。
-
易于擴(kuò)展:增加新的產(chǎn)品類時,只需在工廠類中新增相應(yīng)的創(chuàng)建邏輯即可,對其他類的修改較小,遵循開閉原則(在擴(kuò)展時,不需要修改現(xiàn)有代碼,只需要增加新的代碼)。
? 但是,簡單工廠模式也有其局限性:
- 工廠類的職責(zé)相對比較重,如果產(chǎn)品種類非常多,工廠方法會變得非常復(fù)雜。
- 當(dāng)增加新產(chǎn)品時,需要修改工廠類,這違反了開閉原則(對擴(kuò)展開放,對修改封閉)。
????????
3.4 簡單工廠模式優(yōu)缺點
? 優(yōu)點:
- 幫助封裝:簡單工廠雖然很簡單,但是非常友好幫我們實現(xiàn)了組件的封裝,然后讓組件外部能真正面向接口編程。
-
解耦:通過簡單工廠,實現(xiàn)了客戶端和具體實現(xiàn)類的解耦。如同上面的例子,客戶端根本就不知道具體是由誰來實現(xiàn),也不知道具體是如何實現(xiàn)的,客戶端只是通過工廠獲取它需要的接口對象。
? 缺點:
-
可能增加客戶端的復(fù)雜度:如果通過客戶端的參數(shù)來選擇具體的實現(xiàn)類,那么就必須讓客戶端能理解各個參數(shù)所代表的具體功能和含義,這樣會增加客戶端使用的難度,也部分暴露了內(nèi)部實現(xiàn),這種情況可以選用可配置的方式來實現(xiàn)。
-
不方便擴(kuò)展子工廠:私有化簡單工廠的構(gòu)造方法,使用靜態(tài)方法來創(chuàng)建接口,也就不能通過寫簡單工廠類的子類來改變創(chuàng)建接口的方法的行為了。不過,通常情況下是不需要為簡單工廠創(chuàng) 建子類的。
????????
3.5 思考簡單工廠模式
3.5.1 本質(zhì)
筒單工廠的本質(zhì)是:選擇實現(xiàn)。
? ? 簡單工廠的重點在選擇,實現(xiàn)是已經(jīng)做好了的。就算實現(xiàn)再簡單,也要由具體的實現(xiàn)類來實現(xiàn),而不是在簡單工廠里面來實現(xiàn)。簡單工廠的目的在于為客戶端來選擇相應(yīng)的實現(xiàn),從而使得客戶端和實現(xiàn)之間解耦。這樣一來,具體實現(xiàn)發(fā)生了變化,就不用變動客戶端了,這個變化會被簡單工廠吸收和屏蔽掉。
? ? 實現(xiàn)簡單工廠的難點就在于 “如何選擇” 實現(xiàn),前面便子中傳遞參數(shù)的方法, 那都是靜態(tài)的參數(shù),還可以實現(xiàn)成為動態(tài)的參數(shù)。比如,在運行期間,由工廠去讀取某個內(nèi)存的值,或者是去讀取數(shù)據(jù)庫中的值,然后根據(jù)這個值來選擇具體的實現(xiàn)等。
????????
3.5.2 何時選用簡單工廠模式
? 建議在以 下情況中選用簡單工廠:
- 如果想要完全封裝隔離具體實現(xiàn),讓外部只能通過接又來操作封裝體,那么可 以選用簡單工廠,讓客戶端通過工廠來獲取相應(yīng)的接又,而無須關(guān)心具體的實現(xiàn)。
-
如果想要把對外創(chuàng)建對象的職責(zé)集中管理和控制,可以選用簡單工廠,一個簡 單工廠可以創(chuàng)建很多的、不相關(guān)的對象,可以把對外創(chuàng)建對象的職責(zé)集中到一個簡單 工廠來,從而實現(xiàn)集中管理和控制。
????????
3.6 相關(guān)設(shè)計模式結(jié)合
? ? 簡單工廠模式本身是一個非?;A(chǔ)的創(chuàng)建型模式,它是許多更復(fù)雜設(shè)計模式的起點。雖然它具有一定的局限性,但是在與其他設(shè)計模式結(jié)合使用時,它可以幫助更好地組織和管理代碼。以下是幾種與簡單工廠模式相結(jié)合的設(shè)計模式,以及這種結(jié)合的好處:
-
策略模式(Strategy Pattern):
簡單工廠可以創(chuàng)建策略模式中的各種策略對象。策略模式允許您在運行時根據(jù)不同的情境切換算法或策略。當(dāng)結(jié)合簡單工廠時,您可以隱藏創(chuàng)造這些策略的邏輯,簡化策略的更換過程,進(jìn)而使得客戶代碼在使用時,只需要關(guān)注策略接口而不是實現(xiàn)。 -
工廠方法模式(Factory Method Pattern):
雖然簡單工廠模式不是工廠方法模式,但是它可以被視為是工廠方法模式的一種特例,當(dāng)只有一個具體工廠類時。如果產(chǎn)品的創(chuàng)建邏輯比較簡單,且不需要擴(kuò)展額外的工廠類,使用簡單工廠可能更為簡便。 -
單例模式(Singleton Pattern):
簡單工廠和單例模式可以結(jié)合起來用于確保特定類型只有一個實例被創(chuàng)建。例如,簡單工廠可以返回應(yīng)用程序中唯一的數(shù)據(jù)庫連接實例或配置對象,從而保證資源的統(tǒng)一管理。 -
外觀模式(Facade Pattern):
簡單工廠可能被用于實現(xiàn)一個外觀類的一部分,這個外觀類提供了一個簡化的接口,用于隱藏更復(fù)雜的子系統(tǒng)。外觀模式經(jīng)常與簡單工廠一起使用,進(jìn)一步簡化客戶端和子系統(tǒng)之間的交互。 -
適配器模式(Adapter Pattern):
當(dāng)需要提供多個適配器類的實例時,簡單工廠可以幫助創(chuàng)建這些類,無論是對象適配器還是類適配器,簡單工廠都可以根據(jù)不同情況和需求來創(chuàng)建合適的適配器實例。 -
建造者模式(Builder Pattern):
在某些情況下,可以使用簡單工廠來選擇并創(chuàng)建具體的建造者實例。建造者模式通常用于創(chuàng)建復(fù)雜的對象,其中對象的創(chuàng)建過程需要多個步驟和過程。簡單工廠可用于封裝這一選擇過程。