日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

设计模式(一) 工厂模式 五种写法总结

發(fā)布時(shí)間:2023/12/8 asp.net 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 设计模式(一) 工厂模式 五种写法总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載請(qǐng)標(biāo)明出處:
http://blog.csdn.net/zxt0601/article/details/52798423

本文出自:【張旭童的博客】

系列開篇瞎BB

設(shè)計(jì)模式相關(guān)的文章學(xué)習(xí)與總結(jié),一直有意為之,一直又覺得時(shí)機(jī)不到。

一 是怕自己代碼經(jīng)驗(yàn)還不夠,學(xué)習(xí)了也不懂,強(qiáng)行理解沒有意義。

二 是怕自己學(xué)習(xí)了以后總結(jié)出來,萬一有不對(duì)的地方,誤人子弟。

而在現(xiàn)在的公司摸爬滾打半年后,感覺自己寫代碼遇到了瓶頸,想寫好寫優(yōu)雅,卻不清楚這么寫究竟是自以為優(yōu)雅 還是真的優(yōu)雅。或?qū)χ匆恍┫到y(tǒng)源碼、框架源碼時(shí),不太理解他們這么寫是為什么。

于是我開始了學(xué)習(xí)之路,從比較簡(jiǎn)單的工廠模式開刀,看了大概10+篇資料,發(fā)現(xiàn)各位大大對(duì)工廠模式的各種寫法叫法不一,理解也不一,而且沒有一篇是比較全的收錄各種寫法的。so,這也堅(jiān)定了我將它總結(jié)寫出來的決心,既然每個(gè)人的理解都有或多或少的缺失或沖突,那我也總結(jié)一份我的理解,呈現(xiàn)出來,供各位看官參考 點(diǎn)評(píng)。

一概述:

屬于創(chuàng)建型設(shè)計(jì)模式,需要生成的對(duì)象叫做產(chǎn)品 ,生成對(duì)象的地方叫做工廠 。

使用場(chǎng)景:

在任何需要生成復(fù)雜對(duì)象的地方,都可以使用工廠方法模式。
直接用new可以完成的不需要用工廠模式

個(gè)人理解,重點(diǎn)就是這個(gè)復(fù)雜 (構(gòu)造函數(shù)有很多參數(shù))和 是否可以 直接用new。(不理解這句話的話,看完一圈例子就理解了)

下面逐個(gè)介紹我所知道的各種工廠模式以及它們的特點(diǎn),使用場(chǎng)景,并盡可能的找出JDK SDK里它們的身影。


二 簡(jiǎn)單(靜態(tài))工廠:

一個(gè)栗子:
我喜歡吃面條,抽象一個(gè)面條基類,(接口也可以),這是產(chǎn)品的抽象類。

public abstract class INoodles {/*** 描述每種面條啥樣的*/public abstract void desc(); }

先來一份蘭州拉面(具體的產(chǎn)品類):

public class LzNoodles extends INoodles {@Overridepublic void desc() {System.out.println("蘭州拉面 上海的好貴 家里才5 6塊錢一碗");} }

程序員加班必備也要吃泡面(具體的產(chǎn)品類):

public class PaoNoodles extends INoodles {@Overridepublic void desc() {System.out.println("泡面好吃 可不要貪杯");} }

還有我最愛吃的家鄉(xiāng)的干扣面(具體的產(chǎn)品類):

public class GankouNoodles extends INoodles {@Overridepublic void desc() {System.out.println("還是家里的干扣面好吃 6塊一碗");} }

準(zhǔn)備工作做完了,我們來到一家“簡(jiǎn)單面館”(簡(jiǎn)單工廠類),菜單如下:

public class SimpleNoodlesFactory {public static final int TYPE_LZ = 1;//蘭州拉面public static final int TYPE_PM = 2;//泡面public static final int TYPE_GK = 3;//干扣面public static INoodles createNoodles(int type) {switch (type) {case TYPE_LZ:return new LzNoodles();case TYPE_PM:return new PaoNoodles();case TYPE_GK:default:return new GankouNoodles();}} }

簡(jiǎn)單面館就提供三種面條(產(chǎn)品),你說你要啥,他就給你啥。這里我點(diǎn)了一份干扣面:

/*** 簡(jiǎn)單工廠模式*/INoodles noodles = SimpleNoodlesFactory.createNoodles(SimpleNoodlesFactory.TYPE_GK);noodles.desc();

輸出:

還是家里的干扣面好吃 6塊一碗

特點(diǎn)

1 它是一個(gè)具體的類,非接口 抽象類。有一個(gè)重要的create()方法,利用if或者 switch創(chuàng)建產(chǎn)品并返回。

2 create()方法通常是靜態(tài)的,所以也稱之為靜態(tài)工廠

缺點(diǎn)

1 擴(kuò)展性差(我想增加一種面條,除了新增一個(gè)面條產(chǎn)品類,還需要修改工廠類方法)

2 不同的產(chǎn)品需要不同額外參數(shù)的時(shí)候 不支持。

三 另一種簡(jiǎn)單工廠(反射):

利用反射Class.forName(clz.getName()).newInstance()實(shí)現(xiàn)的簡(jiǎn)單工廠:

public class StaticNoodlesFactory {/*** 傳入Class實(shí)例化面條產(chǎn)品類** @param clz* @param <T>* @return*/public static <T extends INoodles> T createNoodles(Class<T> clz) {T result = null;try {result = (T) Class.forName(clz.getName()).newInstance();} catch (Exception e) {e.printStackTrace();}return result;} }

點(diǎn)菜時(shí):

/*** 另一種簡(jiǎn)單工廠* 利用Class.forName(clz.getName()).newInstance()*/System.out.println("=====另一種簡(jiǎn)單工廠利用Class.forName(clz.getName()).newInstance()======" +"\n個(gè)人覺得不好,因?yàn)檫@樣和簡(jiǎn)單的new一個(gè)對(duì)象一樣,工廠方法應(yīng)該用于復(fù)雜對(duì)象的初始化" +"\n 這樣像為了工廠而工廠");//蘭州拉面INoodles lz = StaticNoodlesFactory.createNoodles(LzNoodles.class);lz.desc();//泡面INoodles pm = StaticNoodlesFactory.createNoodles(PaoNoodles.class);pm.desc();

輸出:

=====另一種簡(jiǎn)單工廠利用Class.forName(clz.getName()).newInstance()====== 個(gè)人覺得不好,因?yàn)檫@樣和簡(jiǎn)單的new一個(gè)對(duì)象一樣,工廠方法應(yīng)該用于復(fù)雜對(duì)象的初始化這樣像為了工廠而工廠 蘭州拉面 上海的好貴 家里才5 6塊錢一碗 泡面好吃 可不要貪杯

特點(diǎn)

1 它也是一個(gè)具體的類,非接口 抽象類。但它的create()方法,是利用反射機(jī)制生成對(duì)象返回,好處是增加一種產(chǎn)品時(shí),不需要修改create()的代碼

缺點(diǎn)

這種寫法粗看牛逼,細(xì)想之下,不談reflection的效率還有以下問題:

1 個(gè)人覺得不好,因?yàn)镃lass.forName(clz.getName()).newInstance()調(diào)用的是無參構(gòu)造函數(shù)生成對(duì)象,它和new Object()是一樣的性質(zhì),而工廠方法應(yīng)該用于復(fù)雜對(duì)象的初始化 ,當(dāng)需要調(diào)用有參的構(gòu)造函數(shù)時(shí)便無能為力了,這樣像為了工廠而工廠。

2 不同的產(chǎn)品需要不同額外參數(shù)的時(shí)候 不支持。

四 多方法工廠(常用)

使用方法二 三實(shí)現(xiàn)的工廠,都有一個(gè)缺點(diǎn):不同的產(chǎn)品需要不同額外參數(shù)的時(shí)候 不支持。

而且如果使用時(shí)傳遞的type、Class出錯(cuò),將不能得到正確的對(duì)象,容錯(cuò)率不高。

而多方法的工廠模式為不同產(chǎn)品,提供不同的生產(chǎn)方法,使用時(shí) 需要哪種產(chǎn)品就調(diào)用該種產(chǎn)品的方法,使用方便、容錯(cuò)率高

工廠如下:

public class MulWayNoodlesFactory {/*** 模仿Executors 類* 生產(chǎn)泡面** @return*/public static INoodles createPm() {return new PaoNoodles();}/*** 模仿Executors 類* 生產(chǎn)蘭州拉面** @return*/public static INoodles createLz() {return new LzNoodles();}/*** 模仿Executors 類* 生產(chǎn)干扣面** @return*/public static INoodles createGk() {return new GankouNoodles();} }

使用時(shí):

/*** 多方法靜態(tài)工廠(模仿Executor類)*/System.out.println("==============================模仿Executor類==============================" +"\n 這種我比較青睞,增加一個(gè)新面條,只要去增加一個(gè)static方法即可,也不修改原方法邏輯");INoodles lz2 = MulWayNoodlesFactory.createLz();lz2.desc();INoodles gk2 = MulWayNoodlesFactory.createGk();gk2.desc();

輸出:

==============================模仿Executor類============================== 這種我比較青睞,增加一個(gè)新面條,只要去增加一個(gè)static方法即可,也不修改原方法邏輯 蘭州拉面 上海的好貴 家里才5 6塊錢一碗 還是家里的干扣面好吃 6塊一碗

源碼撐腰環(huán)節(jié)

查看java源碼:java.util.concurrent.Executors類便是一個(gè)生成Executor 的工廠 ,其采用的便是 多方法靜態(tài)工廠模式

例如ThreadPoolExecutor類構(gòu)造方法有5個(gè)參數(shù),其中三個(gè)參數(shù)寫法固定,前兩個(gè)參數(shù)可配置,如下寫。

public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());}

又如JDK想增加創(chuàng)建ForkJoinPool類的方法了,只想配置parallelism參數(shù),便在類里增加一個(gè)如下的方法:

public static ExecutorService newWorkStealingPool(int parallelism) {return new ForkJoinPool(parallelism,ForkJoinPool.defaultForkJoinWorkerThreadFactory,null, true);}

這個(gè)例子可以感受到工廠方法的魅力了吧:方便創(chuàng)建 同種類型的 復(fù)雜參數(shù) 對(duì)象。

五 普通工廠

普通工廠就是把簡(jiǎn)單工廠中具體的工廠類,劃分成兩層:抽象工廠層+具體的工廠子類層。(一般->特殊)

面條工廠(抽象工廠類),作用就是生產(chǎn)面條:

public abstract class NoodlesFactory {public abstract INoodles create(); }

蘭州拉面工廠 (具體工廠子類):

public class LzFactory extends NoodlesFactory {@Overridepublic INoodles create() {return new LzNoodles();} }

泡面工廠 (具體工廠子類):

public class PaoFactory extends NoodlesFactory {@Overridepublic INoodles create() {return new PaoNoodles();} }

最愛的干扣面工廠 (具體工廠子類):

public class GankouFactory extends NoodlesFactory {@Overridepublic INoodles create() {return new GankouNoodles();} }

使用時(shí):

/*** 普通工廠方法:*/System.out.println("===========================普通工廠方法==============================" +"\n 這種要多寫一個(gè)類,不過更面向?qū)ο蟀?= = ,實(shí)際中我更傾向于使用【模仿Executor類】的方式");NoodlesFactory factory1 = new GankouFactory();INoodles gk3 = factory1.create();gk3.desc();

輸出:

===========================普通工廠方法============================== 這種要多寫一個(gè)類,不過更面向?qū)ο蟀?= = ,實(shí)際中我更傾向于使用【模仿Executor類】的方式 還是家里的干扣面好吃 6塊一碗

普通工廠與簡(jiǎn)單工廠模式的區(qū)別:

可以看出,普通工廠模式特點(diǎn):不僅僅做出來的產(chǎn)品要抽象, 工廠也應(yīng)該需要抽象。

工廠方法使一個(gè)產(chǎn)品類的實(shí)例化延遲到其具體工廠子類.

工廠方法的好處就是更擁抱變化。當(dāng)需求變化,只需要增刪相應(yīng)的類,不需要修改已有的類

而簡(jiǎn)單工廠需要修改工廠類的create()方法,多方法靜態(tài)工廠模式需要增加一個(gè)靜態(tài)方法。

缺點(diǎn):

引入抽象工廠層后,每次新增一個(gè)具體產(chǎn)品類,也要同時(shí)新增一個(gè)具體工廠類,所以我更青睞 多方法靜態(tài)工廠。

六 抽象工廠:

以上介紹的工廠都是單產(chǎn)品系的。抽象工廠是多產(chǎn)品系 (貌似也有產(chǎn)品家族的說法)。

舉個(gè)例子來說,每個(gè)店(工廠)不僅僅賣面條,還提供飲料賣。
提供飲料賣,飲料是產(chǎn)品,先抽象一個(gè)產(chǎn)品類,飲料:

public abstract class IDrinks {/*** 描述每種飲料多少錢*/public abstract void prices(); }

然后實(shí)現(xiàn)兩個(gè)具體產(chǎn)品類:
可樂:

public class ColaDrinks extends IDrinks {@Overridepublic void prices() {System.out.println("可樂三塊五");} }

屌絲還是多喝水吧:

public class WaterDrinks extends IDrinks {@Overridepublic void prices() {System.out.println("和我一樣的窮鬼都喝水,不要錢~!");} }

抽象飯店,無外乎吃喝(抽象工廠類):

public abstract class AbstractFoodFactory {/*** 生產(chǎn)面條** @return*/public abstract INoodles createNoodles();/*** 生產(chǎn)飲料*/public abstract IDrinks createDrinks(); }

蘭州大酒店(具體工廠類):

public class LzlmFoodFactory extends AbstractFoodFactory {@Overridepublic INoodles createNoodles() {return new LzNoodles();//賣蘭州拉面}@Overridepublic IDrinks createDrinks() {return new WaterDrinks();//賣水} }

KFC(具體工廠類):

public class KFCFoodFactory extends AbstractFoodFactory {@Overridepublic INoodles createNoodles() {return new PaoNoodles();//KFC居然賣泡面}@Overridepublic IDrinks createDrinks() {return new ColaDrinks();//賣可樂} }

使用:

/*** 抽象工廠方法:*/System.out.println("==============================抽象方法==============================" +"\n 老實(shí)說,以我這一年的水平我體會(huì)不到抽象工廠有何巨大優(yōu)勢(shì),所以在我這里我沒有想到很好的使用場(chǎng)景。希望以后在慢慢體會(huì)吧。");AbstractFoodFactory abstractFoodFactory1 = new KFCFoodFactory();abstractFoodFactory1.createDrinks().prices();abstractFoodFactory1.createNoodles().desc();abstractFoodFactory1= new LzlmFoodFactory();abstractFoodFactory1.createDrinks().prices();abstractFoodFactory1.createNoodles().desc();

輸出:

==============================抽象方法============================== 老實(shí)說,以我這一年的水平我體會(huì)不到抽象工廠有何巨大優(yōu)勢(shì),所以在我這里我沒有想到很好的使用場(chǎng)景。希望以后在慢慢體會(huì)吧。 可樂三塊五 泡面好吃 可不要貪杯 和我一樣的窮鬼都喝水,不要錢~! 蘭州拉面 上海的好貴 家里才5 6塊錢一碗

小結(jié):

將工廠也抽象了,在使用時(shí),工廠和產(chǎn)品都是面向接口編程,OO(面向?qū)ο?#xff09;的不得了。

缺點(diǎn)

但是將工廠也抽象后,有個(gè)顯著問題,就是類爆炸了。而且每次拓展新產(chǎn)品種類,例如不僅賣吃賣喝,我還想賣睡,提供床位服務(wù),這需要修改抽象工廠類,因此所有的具體工廠子類,都被牽連,需要同步被修改。

老實(shí)說,以我這一年的水平我體會(huì)不到抽象工廠有何巨大優(yōu)勢(shì),所以在我這里我沒有想到很好的使用場(chǎng)景。希望以后在慢慢體會(huì)吧。如有您知道,希望不吝賜教。


七 個(gè)人總結(jié)和使用場(chǎng)景

一句話總結(jié)工廠模式:方便創(chuàng)建 同種產(chǎn)品類型的 復(fù)雜參數(shù) 對(duì)象

工廠模式重點(diǎn)就是適用于 構(gòu)建同產(chǎn)品類型(同一個(gè)接口 基類)的不同對(duì)象時(shí),這些對(duì)象new很復(fù)雜,需要很多的參數(shù),而這些參數(shù)中大部分都是固定的,so,懶惰的程序員便用工廠模式封裝之。
(如果構(gòu)建某個(gè)對(duì)象很復(fù)雜,需要很多參數(shù),但這些參數(shù)大部分都是“不固定”的,應(yīng)該使用Builder模式)

為了適應(yīng)程序的擴(kuò)展性,擁抱變化,便衍生出了 普通工廠、抽象工廠等模式。

代碼傳送門:
github:
https://github.com/mcxtzhang/Demos/tree/master/libfactorypattern

學(xué)習(xí)參考:

http://blog.csdn.net/zhangerqing/article/details/8194653
http://blog.csdn.net/column/details/code-design.html
Android源碼設(shè)計(jì)模式書籍
Java設(shè)計(jì)模式深入研究書籍
一些搜 工廠模式 出來的文章….

總結(jié)

以上是生活随笔為你收集整理的设计模式(一) 工厂模式 五种写法总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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