【转载】创建型-工厂方法模式
介紹:
在簡單工廠模式中,我們提到,工廠方法模式是簡單工廠模式的一個(gè)延伸,它屬于Gof23中設(shè)計(jì)模式的創(chuàng)建型設(shè)計(jì)模式。它解決的仍然是軟件設(shè)計(jì)中與創(chuàng)建對(duì)象有關(guān)的問題。它可以更好的處理客戶的需求變化。
引入
我們繼續(xù)來說"new"的問題,我們?cè)诤唵喂S模式中,將實(shí)例化對(duì)象的工作推遲到了專門負(fù)責(zé)創(chuàng)建對(duì)象的工廠類中,這樣,在我們事先預(yù)知的情況下,可以根據(jù)我們的需要?jiǎng)討B(tài)創(chuàng)建產(chǎn)品類。但是,我們的預(yù)知是有限的,客戶的變化可能是無限的。所以,就出現(xiàn)了問題,一旦客戶的變化超越了我們的預(yù)知,我們就必須修改我們的源代碼了。這是設(shè)計(jì)模式所不允許的,怎么辦呢?工廠方法模式正是解決此類問題的。
問題:具體工廠類的創(chuàng)建工作不能滿足我們的要求了,創(chuàng)建的工作變化了
解決思路:哪里變化,封裝哪里。把具體工廠封裝起來。
定義
工廠方法模式又稱為工廠模式,也叫虛擬構(gòu)造器(Virtual Constructor)模式或者多態(tài)工廠模式(Polymorphic Factory),在工廠方法模式中,父類負(fù)責(zé)定義創(chuàng)建對(duì)象的公共接口,而子類則負(fù)責(zé)生成具體的對(duì)象,這樣做的目的是將類的實(shí)例化操作延遲到子類中完成,即由子類來決定究竟應(yīng)該實(shí)例化(創(chuàng)建)哪一個(gè)類。
意圖
定義一個(gè)用戶創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪一個(gè)類,工廠方法模式使一個(gè)類的實(shí)例化延遲到其子類。
參與者
- 抽象產(chǎn)品角色(Product)
定義產(chǎn)品的接口 - 具體產(chǎn)品角色(ConcreteProduct)
實(shí)現(xiàn)接口Product的具體產(chǎn)品類 - 抽象工廠角色(Creator)
聲明工廠方法(FactoryMethod),返回一個(gè)產(chǎn)品 - 真實(shí)的工廠(ConcreteCreator)
實(shí)現(xiàn)FactoryMethod工廠方法,由客戶調(diào)用,返回一個(gè)產(chǎn)品的實(shí)例
工廠方法模式UML圖
現(xiàn)實(shí)生活中的例子
為了方便大家理解,我仍然舉穿衣服方面的一個(gè)例子。這個(gè)例子與簡單工廠模式中的那個(gè)例子有些不同。
據(jù)說清朝有個(gè)皇帝穿衣非常的奢侈,每種衣服(具體產(chǎn)品類)由一宮女(具體工廠類)專門負(fù)責(zé),這樣一來,每增加一種衣服(具體產(chǎn)品類),就要多出一個(gè)宮女(具體工廠類),但是他們各負(fù)其責(zé),互不影響。皇帝之所以這樣做,是因?yàn)獒槍?duì)穿衣服這件事來說,可擴(kuò)展性是非常強(qiáng)的()。
分析
實(shí)現(xiàn)的功能:可以根據(jù)皇帝的要求,動(dòng)態(tài)的創(chuàng)建(由宮女去拿)已存在的具體產(chǎn)品(衣服),如果皇帝的要求太苛刻,這種衣服還沒有,只需要增加一個(gè)宮女,一個(gè)衣服就能夠滿足他的要求了。每個(gè)宮女只負(fù)責(zé)一種衣服(高內(nèi)聚),要增加一種衣服,對(duì)于以前的所有宮女與衣服來說,都不會(huì)受到影響(設(shè)計(jì)模式中所期望的)。說到這里,是不是明白了工廠方法模式所能解決的問題及其應(yīng)用了?呵呵。。你一定在想,比簡單工廠模式靈活性高吧。。
抽象工廠角色代碼
?
抽象產(chǎn)品角色代碼
?2{
?3????/**////?<summary>
?4????///?抽象產(chǎn)品類
?5????///?</summary>
?6????public?interface?ICoat
?7????{
?8????????void?ShowCoat();
?9????}
10}
?
具體工廠角色代碼
?
?1namespace?FactoryMethod?2{
?3????/**////?<summary>
?4????///?具體工廠類:用于創(chuàng)建商務(wù)上衣類
?5????///?</summary>
?6????public?class?BusinessFactory:IFactory
?7????{????????
?8????????public?ICoat?CreateCoat()
?9????????{
10????????????return?new?BusinessCoat();
11????????}
12????}
13
14????/**////?<summary>
15????///?具體工廠類,用于創(chuàng)建時(shí)尚上衣
16????///?</summary>
17????public?class?FashionFactory?:?IFactory
18????{
19????????public?ICoat?CreateCoat()
20????????{
21????????????return?new?FashionCoat();
22????????}
23????}
24}
?
具體產(chǎn)品角色代碼
?
?1namespace?FactoryMethod?2{
?3????/**////?<summary>
?4????///?具體產(chǎn)品類,商務(wù)上衣類
?5????///?</summary>
?6????public?class?BusinessCoat:ICoat
?7????{
?8????????public?void?ShowCoat()
?9????????{
10????????????Console.WriteLine("這件是商務(wù)上衣");
11????????}
12????}
13
14????/**////?<summary>
15????///?具體產(chǎn)品類,時(shí)尚上衣類
16????///?</summary>
17????public?class?FashionCoat?:?ICoat
18????{
19????????public?void?ShowCoat()
20????????{
21????????????Console.WriteLine("這件是時(shí)尚上衣");
22????????}
23????}
24}
25
?
客戶端代碼
?
?1namespace?FactoryMethod?2{
?3????/**////?<summary>
?4????///?客戶端代碼
?5????///?</summary>
?6????class?Client
?7????{
?8????????static?void?Main(string[]?args)
?9????????{
10????????????//為了方便以后修改,將工廠類的類名寫在應(yīng)用程序配置文件中
11????????????string?factoryName?=?ConfigurationManager.AppSettings["FactoryName"];
12??????????
13????????????IFactory?factory?=?(IFactory)Assembly.Load("ConcreteFactory").CreateInstance("FactoryMethod."?+?factoryName);
14????????????
15????????????ICoat?coat?=?factory.CreateCoat();
16????????????//顯示你要的上衣
17????????????coat.ShowCoat();
18????????}
19????}
20}
?
客戶端代碼需要注意的兩個(gè)地方:
1,把具體工廠類類名稱寫在了應(yīng)用程序配置文件中,方便修改
2,用到了反射,利用.NET提供的反射可以根據(jù)類名來創(chuàng)建它的實(shí)例,非常方便
由反射想到的:
下面這一段內(nèi)容不是計(jì)劃要寫的。
如果在具體工廠中,每次new的對(duì)象都是一個(gè),而且這些類是繼承自抽象產(chǎn)品接口的,那么我們用簡單工廠模式也可以實(shí)現(xiàn)動(dòng)態(tài)的增加具體產(chǎn)品類。這樣來做,在簡單工廠模式中最核心的部分----工廠類不要根據(jù)傳來的條件去動(dòng)態(tài)創(chuàng)建產(chǎn)品類,利用反射機(jī)制去創(chuàng)建。把要實(shí)例化的類名放在應(yīng)用程序配置文件中,呵呵。。這樣利用.NET特有的反射就可以用簡單工廠模式解決更多的問題了,工廠方法模式的一部分問題也是可以通過“這樣的簡單工廠模式”解決的,在需要增加具體產(chǎn)品類時(shí),不用增加具體工廠,是不是簡單一些呀。下去試一下。。。
優(yōu)點(diǎn):
?
- 基于工廠角色和產(chǎn)品角色的多態(tài)性設(shè)計(jì)是工廠方法模式的關(guān)鍵。它能夠使工廠可以自主確定創(chuàng)建何種產(chǎn)品對(duì)象。而且如何創(chuàng)建一個(gè)具體產(chǎn)品的細(xì)節(jié)完全封裝在具體工廠內(nèi)部,符合高內(nèi)聚,低耦合。
- 在系統(tǒng)中加入新產(chǎn)品時(shí),無需修改抽象工廠和抽象產(chǎn)品提供的接口,無需修改客戶端,也無需修改其他的具體工廠和具體產(chǎn)品,很好的利用了封裝和委托。
?
缺點(diǎn):
?
- 在添加新產(chǎn)品時(shí),需要編寫新的具體產(chǎn)品類(其實(shí)這不算一個(gè)缺點(diǎn),因?yàn)檫@是不可避免的),要增加與之對(duì)應(yīng)的具體工廠類。
?
應(yīng)用情景:
?
- 類不知道自己要?jiǎng)?chuàng)建哪一個(gè)對(duì)象時(shí)
- 類用它的子類來指定創(chuàng)建哪個(gè)對(duì)象
- 當(dāng)類將創(chuàng)建對(duì)象的職責(zé)委托給多個(gè)幫助子類中的某一個(gè),并且你希望將哪一個(gè)幫助子類是代理者這一信息局部化的時(shí)候??
?
工廠方法模式在ASP.NET HTTP通道中的應(yīng)用,TerryLee在他的那篇文件中寫的非常好,推薦去看一下。
?
轉(zhuǎn)載于:https://www.cnblogs.com/Loyalty/archive/2012/04/24/2469050.html
總結(jié)
以上是生活随笔為你收集整理的【转载】创建型-工厂方法模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL注入漏洞全接触--高级篇
- 下一篇: 神经网络基本原理简明教程之线性回归预测房