日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

java中的工厂模式

發(fā)布時間:2025/3/21 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java中的工厂模式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、工廠模式介紹

工廠模式專門負(fù)責(zé)將大量有共同接口的類實(shí)例化。工廠模式可以動態(tài)決定將哪一個類實(shí)例化,不必事先知道每次要實(shí)例化哪一個類。

工廠模式的幾種形態(tài):

(1)簡單工廠(Simple Factory)模式,又稱靜態(tài)工廠方法模式(Static Factory Method Pattern)。
(2)工廠方法(Factory Method)模式,又稱多態(tài)性工廠(Polymorphic Factory)模式或虛擬構(gòu)造子(Virtual Constructor)模式;
(3)抽象工廠(Abstract Factory)模式,又稱工具箱(Kit 或Toolkit)模式。

二、簡單工廠模式

2.1簡單工廠模式介紹

簡單工廠模式(Simple Factory Pattern):又稱為靜態(tài)工廠方法(Static Factory Method)模式,它屬于類創(chuàng)建型模式。在簡單工廠模式中,可以根據(jù)自變量的不同返回不同類的實(shí)例。簡單工廠模式專門定義一個類來負(fù)責(zé)創(chuàng)建其他類的實(shí)例,被創(chuàng)建的實(shí)例通常都具有共同的父類。

2.2簡單工廠模式角色

(1)工廠類(Creator)角色:擔(dān)任這個角色的是工廠方法模式的核心,含有與應(yīng)用緊密相關(guān)的商業(yè)邏輯。工廠類在客戶端的直接調(diào)用下創(chuàng)建產(chǎn)品對象,它往往由一個具體Java 類實(shí)現(xiàn)。
(2)抽象產(chǎn)品(Product)角色:擔(dān)任這個角色的類是工廠方法模式所創(chuàng)建的對象的父類,或它們共同擁有的接口。抽象產(chǎn)品角色可以用一個Java 接口或者Java 抽象類實(shí)現(xiàn)。
(3)具體產(chǎn)品(Concrete Product)角色:工廠方法模式所創(chuàng)建的任何對象都是這個角色的實(shí)例,具體產(chǎn)品角色由一個具體Java 類實(shí)現(xiàn)。

2.3簡單工廠模式的優(yōu)缺點(diǎn)

簡單工廠模式的優(yōu)點(diǎn)如下:

(1)工廠類含有必要的判斷邏輯,可以決定在什么時候創(chuàng)建哪一個產(chǎn)品類的實(shí)例,客戶端可以免除直接創(chuàng)建產(chǎn)品對象的責(zé)任,而僅僅“消費(fèi)”產(chǎn)品;簡單工廠模式通過這種做法實(shí)現(xiàn)了對責(zé)任的分割,它提供了專門的工廠類用于創(chuàng)建對象。
(2)客戶端無需知道所創(chuàng)建的具體產(chǎn)品類的類名,只需要知道具體產(chǎn)品類所對應(yīng)的參數(shù)即可,對于一些復(fù)雜的類名,通過簡單工廠模式可以減少使用者的記憶量。
(3)通過引入配置文件,可以在不修改任何客戶端代碼的情況下更換和增加新的具體產(chǎn)品類,在一定程度上提高了系統(tǒng)的靈活性。
簡單工廠模式的缺點(diǎn)如下:

(1)由于工廠類集中了所有產(chǎn)品創(chuàng)建邏輯,一旦不能正常工作,整個系統(tǒng)都要受到影響。
(2)使用簡單工廠模式將會增加系統(tǒng)中類的個數(shù),在一定程序上增加了系統(tǒng)的復(fù)雜度和理解難度。
(3)系統(tǒng)擴(kuò)展困難,一旦添加新產(chǎn)品就不得不修改工廠邏輯,在產(chǎn)品類型較多時,有可能造成工廠邏輯過于復(fù)雜,不利于系統(tǒng)的擴(kuò)展和維護(hù)。
(4)簡單工廠模式由于使用了靜態(tài)工廠方法,造成工廠角色無法形成基于繼承的等級結(jié)構(gòu)。

2.4簡單工廠模式的適用環(huán)境

(1)工廠類負(fù)責(zé)創(chuàng)建的對象比較少:由于創(chuàng)建的對象較少,不會造成工廠方法中的業(yè)務(wù)邏輯太過復(fù)雜;
(2)客戶端只知道傳入工廠類的參數(shù),對于如何創(chuàng)建對象不關(guān)心:客戶端既不需要關(guān)心創(chuàng)建細(xì)節(jié),甚至連類名都不需要記住,只需要知道類型所對應(yīng)的參數(shù)。

2.5簡單工廠模式的舉例

假設(shè)一家工廠,生產(chǎn)電視,汽車等等,我們先為所有產(chǎn)品定義一個共同的產(chǎn)品接口

public interface Product { }

接著我們讓這個工廠的所有產(chǎn)品都必須實(shí)現(xiàn)此接口

public class Tv implements Product {public Tv(){System.out.println("電視被制造了");} }public class Car implements Product {public Car(){System.out.println("汽車被制造了");} }

下面有幾種模式來實(shí)現(xiàn)這個工廠:

2.5.1 直接判斷傳入的key

public class ProductFactory {public static Product produce(String productName) throws Exception {switch (productName) {case "tv":return new Tv();case "car":return new Car();default:throw new Exception("沒有該產(chǎn)品");}} }

測試方法:

try {ProductFactory.produce("car"); } catch (Exception e) {e.printStackTrace(); }

返回結(jié)果:

汽車被制造了

這樣的實(shí)現(xiàn)有個問題,如果我們新增產(chǎn)品類的話,需要不斷的在工廠類中新增case,這樣需要修改的地方比較多,所以不建議使用這樣的方法來實(shí)現(xiàn)工廠類。

2.5.2 利用反射

public class ProductFactory2 {public static Product produce(String className) throws Exception {try {Product product = (Product) Class.forName(className).newInstance();return product;} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}throw new Exception("沒有該產(chǎn)品");} }

測試方法:

try {ProductFactory2.produce("com.zhaofeng.factory.simple.Tv"); } catch (Exception e) {e.printStackTrace(); }

返回結(jié)果:

電視被制造了

這種的缺點(diǎn)在于,每次創(chuàng)建一個產(chǎn)品時,需要傳入產(chǎn)品的全部類路徑,也就是要記住一個產(chǎn)品的全部路徑,比較麻煩。我們想到可以通過配置文件,來將類路徑全部寫在properties文件中,通過加載配置文件,這樣如果以后新增的話,直接修改配置文件即可。

2.5.3 反射加配置文件

新增配置文件product.properties

tv=com.zhaofeng.factory.simple.Tv car=com.zhaofeng.factory.simple.Car

新增配置文件讀取類,將讀出來的內(nèi)容存儲到一個map中

public class PropertyReader {public static Map<String, String> map = new HashMap<>();public Map<String, String> readPropertyFile(String fileName) {Properties pro = new Properties();InputStream in = getClass().getResourceAsStream(fileName);try {pro.load(in);Iterator<String> iterator = pro.stringPropertyNames().iterator();while (iterator.hasNext()) {String key = iterator.next();String value = pro.getProperty(key);map.put(key, value);}in.close();} catch (IOException e) {e.printStackTrace();}return map;} }

全新的工廠類如下:

public class ProductFactory3 {public static Product produce(String key) throws Exception {PropertyReader reader = new PropertyReader();Map<String, String> map = reader.readPropertyFile("product.properties");try {Product product = (Product) Class.forName(map.get(key)).newInstance();return product;} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}throw new Exception("沒有該產(chǎn)品");} }

測試類:

try {ProductFactory3.produce("tv"); } catch (Exception e) {e.printStackTrace(); }

返回結(jié)果:

電視被制造了

當(dāng)然這個方法也有可以改進(jìn)的地方,比如將map在程序啟動時就加載,這樣就不必要每次調(diào)用的時候,都去解析配置文件了,節(jié)省了一批開銷。

三、工廠方法模式

3.1工廠方法模式的介紹

工廠方法模式定義一個用于創(chuàng)建對象的接口,讓子類決定實(shí)例化哪一個類。Factory Method是一個類的實(shí)例化延遲到其子類。
在工廠方法模式中,核心的工廠類不再負(fù)責(zé)所有的產(chǎn)品的創(chuàng)建,而是將具體創(chuàng)建的工作交給子類去做。這個核心類則搖身一變,成為了一個抽象工廠角色,僅負(fù)責(zé)給出具體工廠子類必須實(shí)現(xiàn)的接口,而不接觸哪一個產(chǎn)品類應(yīng)當(dāng)被實(shí)例化這種細(xì)節(jié)。

3.2工廠方法模式角色

(1)抽象工廠(Creator)角色:擔(dān)任這個角色的是工廠方法模式的核心,它是與應(yīng)用程序無關(guān)的。任何在模式中創(chuàng)建對象的工廠類必須實(shí)現(xiàn)這個接口。在上面的系統(tǒng)中這個角色由Java 接口Creator 扮演;在實(shí)際的系統(tǒng)中,這個角色也常常使用抽象Java 類實(shí)現(xiàn)。
(2)具體工廠(Concrete Creator)角色:擔(dān)任這個角色的是實(shí)現(xiàn)了抽象工廠接口的具體Java 類。具體工廠角色含有與應(yīng)用密切相關(guān)的邏輯,并且受到應(yīng)用程序的調(diào)用以創(chuàng)建產(chǎn)品對象。在本系統(tǒng)中給出了兩個這樣的角色,也就是具體Java 類ConcreteCreator1 和ConcreteCreator2。
(3)抽象產(chǎn)品(Product)角色:工廠方法模式所創(chuàng)建的對象的超類型,也就是產(chǎn)品對象的共同父類或共同擁有的接口。在本系統(tǒng)中,這個角色由Java 接口Product 扮演;在實(shí)際的系統(tǒng)中,這個角色也常常使用抽象Java 類實(shí)現(xiàn)。
(4)具體產(chǎn)品(Concrete Product)角色:這個角色實(shí)現(xiàn)了抽象產(chǎn)品角色所聲明的接口。工廠方法模式所創(chuàng)建的每一個對象都是某個具體產(chǎn)品角色的實(shí)例。

3.3工廠方法模式的優(yōu)缺點(diǎn)

工廠方法模式的優(yōu)點(diǎn)如下
(1)在工廠方法模式中,工廠方法用來創(chuàng)建客戶所需要的產(chǎn)品,同時還向客戶隱藏了哪種具體產(chǎn)品類將被實(shí)例化這一細(xì)節(jié),用戶只需要關(guān)心所需產(chǎn)品對應(yīng)的工廠,無需關(guān)心創(chuàng)建細(xì)節(jié),甚至無需知道具體產(chǎn)品類的類名。
(2)基于工廠角色和產(chǎn)品角色的多態(tài)性設(shè)計是工廠方法模式的關(guān)鍵。它能夠使工廠可以自主確定創(chuàng)建何種產(chǎn)品對象,而如何創(chuàng)建這個對象的細(xì)節(jié)則完全封裝在具體工廠內(nèi)部。工廠方法模式之所以又被稱為多態(tài)工廠模式,正是因?yàn)樗械木唧w工廠類都具有同一抽象父類。
(3)使用工廠方法模式的另一個優(yōu)點(diǎn)是在系統(tǒng)中加入新產(chǎn)品時,無需修改抽象工廠和抽象產(chǎn)品提供的接口,無需修改客戶端,也無需修改其他的具體工廠和具體產(chǎn)品,而只要添加一個具體工廠和具體產(chǎn)品就可以了,這樣,系統(tǒng)的可擴(kuò)展性也就變得非常好,完全符合“開閉原則”。
工廠方法模式的缺點(diǎn)如下
(1)在添加新產(chǎn)品時,需要編寫新的具體產(chǎn)品類,而且還要提供與之對應(yīng)的具體工廠類,系統(tǒng)中類的個數(shù)將成對增加,在一定程度上增加了系統(tǒng)的復(fù)雜度,有更多的類需要編譯和運(yùn)行,會給系統(tǒng)帶來一些額外的開銷。
(2)由于考慮到系統(tǒng)的可擴(kuò)展性,需要引入抽象層,在客戶端代碼中均使用抽象層進(jìn)行定義,增加了系統(tǒng)的抽象性和理解難度,且在實(shí)現(xiàn)時可能需要用到DOM、反射等技術(shù),增加了系統(tǒng)的實(shí)現(xiàn)難度。

3.4工廠方法模式的適用環(huán)境

在以下情況下可以使用工廠方法模式
(1)一個類不知道它所需要的對象的類:在工廠方法模式中,客戶端不需要知道具體產(chǎn)品類的類名,只需要知道所對應(yīng)的工廠即可,具體的產(chǎn)品對象由具體工廠類創(chuàng)建;客戶端需要知道創(chuàng)建具體產(chǎn)品的工廠類。
(2)一個類通過其子類來指定創(chuàng)建哪個對象:在工廠方法模式中,對于抽象工廠類只需要提供一個創(chuàng)建產(chǎn)品的接口,而由其子類來確定具體要創(chuàng)建的對象,利用面向?qū)ο蟮亩鄳B(tài)性和里氏代換原則,在程序運(yùn)行時,子類對象將覆蓋父類對象,從而使得系統(tǒng)更容易擴(kuò)展。
(3)將創(chuàng)建對象的任務(wù)委托給多個工廠子類中的某一個,客戶端在使用時可以無需關(guān)心是哪一個工廠子類創(chuàng)建產(chǎn)品子類,需要時再動態(tài)指定,可將具體工廠類的類名存儲在配置文件或數(shù)據(jù)庫中。

3.5舉例

工廠方法為工廠類定義了接口,用多態(tài)來削弱了工廠類的職能,以下是工廠接口的定義:

public interface Factory {public Product produce(); }

我們再來定義一個產(chǎn)品接口

public interface Product{}

以下是實(shí)現(xiàn)了產(chǎn)品接口的產(chǎn)品類:

public class Tv implements Product {public Tv() {System.out.println("電視被制造了");} }public class Car implements Product {public Car(){System.out.println("汽車被制造了");} }

接下來,就是工廠方法的核心部分,也就是具體創(chuàng)建產(chǎn)品對象的具體工廠類,

public class TvFactory implements Factory {@Overridepublic Product produce() {return new Tv();} }public class CarFactory implements Factory {@Overridepublic Product produce() {return new Car();} }

四、抽象工廠模式

4.1抽象工廠模式的介紹

抽象工廠模式提供一個創(chuàng)建一系列或相互依賴的對象的接口,而無需指定它們具體的類。

4.2抽象工廠模式角色

抽象工廠模式涉及到的系統(tǒng)角色
(1)抽象工廠(AbstractFactory)角色:擔(dān)任這個角色的是工廠方法模式的核心,它是與應(yīng)用系統(tǒng)的商業(yè)邏輯無關(guān)的。通常使用Java 接口或者抽象Java 類實(shí)現(xiàn),而所有的具體工廠類必須實(shí)現(xiàn)這個Java 接口或繼承這個抽象Java 類。
(2)具體工廠類(Conrete Factory)角色:這個角色直接在客戶端的調(diào)用下創(chuàng)建產(chǎn)品的實(shí)例。這個角色含有選擇合適的產(chǎn)品對象的邏輯,而這個邏輯是與應(yīng)用系統(tǒng)的商業(yè)邏輯緊密相關(guān)的。通常使用具體Java 類實(shí)現(xiàn)這個角色。
(3)抽象產(chǎn)品(Abstract Product)角色:擔(dān)任這個角色的類是工廠方法模式所創(chuàng)建的對象的父類,或它們共同擁有的接口。通常使用Java 接口或者抽象Java 類實(shí)現(xiàn)這一角色。
(4)具體產(chǎn)品(Concrete Product)角色:抽象工廠模式所創(chuàng)建的任何產(chǎn)品對象都是某一個具體產(chǎn)品類的實(shí)例。這是客戶端最終需要的東西,其內(nèi)部一定充滿了應(yīng)用系統(tǒng)的商業(yè)邏輯。通常使用具體Java 類實(shí)現(xiàn)這個角色。

4.3抽象工廠模式的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

(1) 隔離了具體類的生成,使得用戶不需要知道什么被創(chuàng)建了。
(2) 當(dāng)一個產(chǎn)品族中的多個對象被設(shè)計成一起工作時,它能夠保證客戶端始終只使用同一個產(chǎn)品族中的對象。

缺點(diǎn):

(1)添加新的產(chǎn)品對像時,難以擴(kuò)展抽象工廠以便生產(chǎn)新種類的產(chǎn)品。

4.4抽象工廠模式的適用環(huán)境

(1)一個系統(tǒng)不應(yīng)當(dāng)依賴于產(chǎn)品類實(shí)例如何被創(chuàng)建、組合和表達(dá)的細(xì)節(jié)。這對于所有形態(tài)的工廠模式都是重要的;
(2)一個系統(tǒng)的產(chǎn)品有多于一個的產(chǎn)品族,而系統(tǒng)只消費(fèi)其中某一族的產(chǎn)品;
(3)同屬于同一個產(chǎn)品族的產(chǎn)品是在一起使用的,這一約束必須要在系統(tǒng)的設(shè)計中體現(xiàn)出來;
(4)系統(tǒng)提供一個產(chǎn)品類的庫,所有的產(chǎn)品以同樣的接口出現(xiàn),從而使客戶端不依賴于實(shí)現(xiàn)。

4.5舉例

將汽車和電視定義兩個接口,對他們進(jìn)行分類

public interface Car { }public interface Tv { }

創(chuàng)建汽車和電視的具體產(chǎn)品

public class Audi implements Car {public Audi(){System.out.println("奧迪車生產(chǎn)出來了");} }public class BMW implements Car {public BMW(){System.out.println("一輛寶馬生產(chǎn)出來了");} }public class LeTv implements Tv {public LeTv() {System.out.println("樂視電視被生產(chǎn)出來了");} }public class Sony implements Tv {public Sony(){System.out.println("索尼電視機(jī)被生產(chǎn)出來了");} }

接下來定義工廠行為接口

public interface Factory {public Tv produceTv();public Car produceCar(); }

具體工廠類:

public class FactoryA implements Factory {@Overridepublic Tv produceTv() {return new LeTv();}@Overridepublic Car produceCar() {return new BMW();} }public class FactoryB implements Factory {@Overridepublic Tv produceTv() {return new Sony();}@Overridepublic Car produceCar() {return new Audi();} }

測試類:

public class Test {public static void main(String[] args) {FactoryA factoryA = new FactoryA();factoryA.produceCar();FactoryB factoryB = new FactoryB();factoryB.produceTv();} }

作者:端木軒
鏈接:https://www.jianshu.com/p/bf8341c75304
來源:簡書

總結(jié)

以上是生活随笔為你收集整理的java中的工厂模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。