### 一、上篇回顧
??????? 上篇我們主要講述了抽象工廠模式和工廠模式。并且分析了該模式的應用場景和一些優缺點,并且給出了一些實現的思路和方案,我們現在來回顧一下:
??????? 抽象工廠模式:一個工廠負責所有類型對象的創建,支持無縫的新增新的類型對象的創建。這種情況是通過配置文件來實現的,通過字典映射的方式來實現,不過可能效率上有點低下,可以通過優化的方式
來做,上篇中我們也給出了委托的工廠實現形式,相比之前的簡單工廠模式和工廠模式有了更好的靈活性,并且對具有依賴關系或者組合關系的對象的創建尤為適合。
??????? 上篇中,有不少的朋友提出了一些意見和建議,首先很感謝大伙的支持和鼓勵,有朋友提出來,我畫的圖不夠專業,專業人士應該用UML建模圖來搞,我怎么說呢?我也同意這樣的說法,但是我發現我通過
另外的直觀的圖形,大家一看就能更明白,結合代碼,當然好的UML圖,已經能表述清楚設計的思路和大體實現了,不過說實話,我看著就有點類,特別是UML圖復雜的時候。所以我還是暫時先用這種一般的圖
形來表述我理解的設計模式的思想,看看大伙是什么看法和意見,如果說都說說UML圖的話,那么后面的相關模式,我會主要以UML專業圖來繪制。
??????? 我這里總結下我們以后項目中的可能會用到設計模式 之處或者系統架構的時候,一般情況下有這樣的幾類方案,我們可以在考慮系統的低耦合性的時候的設計:
???????[](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/Windows-Live-Writer/633b606b0863_B56F/image_2.png)基本上來說能掌握上面的幾類情況,基本上設計出來的系統至少是可用的,不知道大家有沒有更多意見和建議。有的請提出來,我會備
注在文章中。
### 二、摘要
本文主要是針對創建型模式中的創建者模式進行講述,創建者模式是創建型模式中最負責的一個設計模式了,創建者負責構建一個對象的各個部分,并且完成組裝的過程,我們可以這么理解創建者模式,創建者模式類似與一個步驟基本固定,但是每個步驟中的具體形式卻又可以變化的這類對象的創建。也許這樣說還是太抽象了,我們這么來理解吧,我感覺讓人最容易理解的形式還是圖形化的形式,不但接受起來容易,并且讓人映象深刻,不知道大家是不是和我有同感呢?下面我們給出一個簡單的例子,通過圖形化的流程來說明吧:我們這里以我們大伙平時最常見的做飯為例吧:
[](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/Windows-Live-Writer/633b606b0863_B56F/image_6.png)可能我這里給出的流程只是我個人理解的或者看到的過程,不代表全部,呵呵,這里只是事例性的說明。
### 三、本文大綱
?????? a、上篇回顧。
?????? b、摘要。
?????? c、本文大綱。
?????? d、創建者模式的特點及使用場景。
?????? e、創建者模式的實現方案。
?????? f、創建者模式使用總結。
?????? g、系列進度。
?????? h、下篇預告。
### 四、創建者模式的特點及使用場景
????? 創建者模式主要是用于創建復雜的一些對象,這些對象的創建步驟基本固定,但是可能具體的對象的組成部分卻又可以自由的變化,現實中的例子很多,但是可能大伙都比較容易理解的就是,我們的自己花錢配置的臺式機或者筆記本,可以這樣理解,這些硬件設備的各個零件,不管是CPU是Intel的還是AMD的,顯卡是華碩的還是小影霸的,不管硬盤是西部數據的還是希捷的,其實想表述的意思就是對象的具體的組成部分可以是變化的,但是可能我們發現對象的這些組成部分的組織起來的過程是相對固定的,那么我們就可以用創建者模式來做,并且我們引入一個引導者(Director)來引導這個對象的組裝過程。可以簡單用圖形化的過程來描述如下:
[](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/Windows-Live-Writer/633b606b0863_B56F/image_10.png)我們上面說明了一個服裝的大概生產過程,這里生產的順序可能會發生變化,或者生產的帽子,上衣等都會發生變化,但是服裝的組裝過程基本上變化不大,都是需要帽子,上衣,褲子的,這時候我們可以通過引導著負責組裝這樣的過程,然后我們在具體的每個部分可以是抽象接口,根據不同的實現創建不同的帽子來完成變化。
### 五、創建者模式的實現方案
####5.1、經典的創建者模式實現
- ?
- 我們先給出經典創建者模式的一個實現形式,然后針對這個經典模式后面提出幾個改進方案,我們這里以上面講述的服裝的過程作為例子來說明下創建者模式的原理和思想,希望大家也能靈活的運用到實際的項目中去。達到學以致用的目的。
我們來看看具體的代碼實現:
?
~~~
/// <summary>
/// 創建對象組織的所有構造步驟接口
/// </summary>
public interface IBuider
{
void BuilderPart1();
void BuilderPart2();
void BuilderPart3();
}
~~~
定義一個服裝對象:
~~~
/// <summary>
/// 服裝對象
/// </summary>
public class Dress
{
/// <summary>
/// 構建帽子
/// </summary>
public void BuildHat()
{
throw new NotImplementedException();
}
/// <summary>
/// 構建上衣
/// </summary>
public void BuilderWaist()
{
throw new NotImplementedException();
}
/// <summary>
/// 構建褲子
/// </summary>
public void BuilderTrousers()
{
throw new NotImplementedException();
}
}
~~~
實現創建對象的具體步驟:
~~~
public class Builder : IBuider
{
private Dress _dress;
public Builder(Dress dress)
{
this._dress = dress;
}
public void BuilderPart1()
{
this._dress.BuildHat();
}
public void BuilderPart2()
{
this._dress.BuilderWaist();
}
public void BuilderPart3()
{
this._dress.BuilderTrousers();
}
public Dress Build()
{
return this._dress;
}
}
~~~
通過指導者指導對象的創建,而具體的對象的創建還是靠對象本身提供的相應方法,Builder只是調用對象的方法完成組裝步驟。Builder內部提供一個返回構造后完整對象的方法,上面給出的方法是
Build()方法。
~~~
/// <summary>
/// 指導者
/// </summary>
public class Director
{
public void Build(IBuider builder)
{
builder.BuilderPart1();
builder.BuilderPart2();
builder.BuilderPart3();
}
}
~~~
通過上面的代碼,我們給出了經典創建者模式的核心代碼形式,那么針對上面無疑有以下的幾個缺點:
1、Ibuilder接口必須定義完整的組裝流程,一旦定義就不能隨意的動態修改。
2、Builder與具體的對象之間有一定的依賴關系,當然這里可以通過接口來解耦來實現靈活性。
3、Builder必須知道具體的流程。
那么針對上面的幾個問題,我們如何來解決呢?我想前面的創建型模式已經給我了足夠的經驗,還是通過配置文件或者其他的形式來提供靈活性。
-
#### 5.2、創建者模式特性+委托實現
####針對上面講述的例子我們可以考慮如下的方式進行改進:
我們先定義一個構造每個對象部分的委托,并且這個方法的參數是動態變化的:
~~~
/// <summary>
/// 定義通用的構造部分的委托
/// </summary>
public delegate void BuildHandler(params object[] items);
~~~
我們通過定義標記來標識對象中的每個部分的構造步驟
~~~
/// <summary>
/// 為對象中的每個步驟打上標記
/// </summary>
[AttributeUsage(AttributeTargets.Method,AllowMultiple=false)]
public class BuildAttribute : Attribute
{
private MethodInfo hander;
private int stepSort;
public MethodInfo BuildHandler
{
get
{
return this.hander;
}
set
{
this.hander = value;
}
}
public int StepSort
{
get
{
return this.stepSort;
}
set
{
this.stepSort = value;
}
}
}
~~~
構造對象的統一接口
~~~
/// <summary>
/// 創建對象組織的所有構造步驟接口
/// </summary>
public interface IBuider
{
void Build<T>() where T : class,new();
}
~~~
下面給出具體的Builder的緩存實現方案代碼
~~~
public class CommonBuilder : IBuider
{
/// <summary>
/// 緩存每個對象的具體的構造步驟
/// </summary>
private Dictionary<Type, List<BuildHandler>> steps = null;
public void Build<T>(T ob) where T : class, new()
{
//從緩存中讀取指定類型的項
List<BuildHandler> handlers = steps[typeof(T)];
foreach (BuildHandler handler in handlers)
{
handler();
}
}
}
~~~
給出一些獲取某個類型內部的所有具有我們的自定義特性標記的MethodInfo列表
~~~
public List<MethodInfo> GetMethodInfoList<T>() where T : class, new()
{
//從緩存中讀取指定類型的項
List<MethodInfo> methods = new List<MethodInfo>();
T target = new T();
MethodInfo[] methodList= typeof(T).GetType().GetMethods();
BuildAttribute[] attributes = null;
foreach (MethodInfo info in methodList)
{
attributes= (BuildAttribute[])info.GetCustomAttributes(typeof(BuildAttribute), true);
if (attributes.Length > 0)
methods.Add(info);
}
return methods;
}
~~~
獲取所有的特性,一般使用這個方法即可獲取所有的具有標記該特性的方法列表和相應的步驟:
~~~
public List<BuildAttribute> GetBuildAttributeList<T>() where T : class, new()
{
List<BuildAttribute> attributes = new List<BuildAttribute>();
BuildAttribute[] attributeList = null;
BuildAttribute attribute = null;
foreach (MethodInfo info in this.methods)
{
//設置特性中要執行的方法
attributeList = (BuildAttribute[])info.GetCustomAttributes(typeof(BuildAttribute), true);
if (attributeList.Length > 0)
{
attribute = attributeList[0];
attribute.BuildHandler = info;
attributes.Add(attribute);
}
}
//緩存步驟
steps.Add(typeof(T), attributes);
return attributes;
}
~~~
具體的Build中的調用代碼實現:
~~~
public T Build<T>(T ob) where T : class, new()
{
List<BuildAttribute> attributeList = GetBuildAttributeList<T>();
T target=new T();
//構造對象的過程
foreach (BuildAttribute item in attributeList)
{
item.BuildHandler.Invoke(target,null);
}
return target;
}
~~~
這樣我們就完成了一個通用的基于標記的自動發現某個類型的標記方法步驟的通用代碼實現,可能大家感覺這樣的方式還是挺麻煩的,那么我們還有沒有更好的改進方案呢?因為每次打標記我還是感覺挺麻煩的,而且代碼量分布的也比較廣泛,我想通過統一配置管理的方式,當然也是可以的,那么我們可以通過下面的方式來進行擴展。
-
#### 5.3、創建者模式配置文件方式實現
配置文件的方式實現創建者,這個怎么說呢,上面的抽象工廠的模式中,我們主要采用了這樣的方式來實現配置的靈活性和擴展性,其實創建者也是一樣的,我們來看看配置文件吧,我想就看配置文件就大概知道了,具體的應用代碼了,請看下圖,粗略描述了實現的思路:
[](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/Windows-Live-Writer/633b606b0863_B56F/image_7.png)
我這里給出配置文件的父子級節點示例:
?
~~~
<?xml version="1.0" encoding="utf-8" ?>
<Build>
<BuildClass name="ClassName" type="ClassType">
<BuildStep StepOrder="1" MethodName="MethodName1"/>
<BuildStep StepOrder="2" MethodName="MethodName2" />
</BuildClass>
<BuildClass name="ClassName1" type="ClassType1">
<BuildStep StepOrder="1" MethodName="MethodName1"/>
<BuildStep StepOrder="2" MethodName="MethodName2" />
</BuildClass>
</Build>
~~~
我們這里通過在Build實現中讀取配置文件中的所有的步驟,放在字典中。給出示例代碼
~~~
/// <summary>
/// 創建對象組織的所有構造步驟接口
/// </summary>
public class Buider : IBuider
{
private Dictionary<Type, List<MethodInfo>> steps = null;
public Buider()
{
steps = new Dictionary<Type, List<MethodInfo>>();
//讀取配置文件!
//將配置文件中的類名和方法名取出,然后通過反射取到這個類型下的所有方法,根據配置中的步驟和方法名添加到
//步驟列表中,然后緩存到字典中
steps.Add(Type.GetType(""), new List<MethodInfo>());
}
public T Build<T>() where T: class,new()
{
T target = new T();
//從字典中找到對應的緩存列表,執行構造過程
List<MethodInfo> list = steps[typeof(T)];
//執行構造
foreach (MethodInfo info in list)
{
info.Invoke(target, null);
}
return target;
}
}
~~~
通過上面的幾步配置就可以完成相應的構建過程,這時候我們的指導者的工作就簡單了,就是只是簡單的通過使用Build中的通用方法
~~~
public class Director
{
public void Build<T>(IBuider builder) where T:class,new()
{
builder.Build<T>();
}
}
~~~
只要通過上面的步驟就完成了創建者模式的通用實現方案。
### 六、創建者模式使用總結
通過上面的給出的幾類不同的實現方案我們知道,創建者模式是一個對對象的構建過程“精細化”的構建過程,每個部分的構建可能是變化的,但是對象的組織過程是固定的,通過這種統一的創建方式,無疑增加了我們設計上的靈活性,當我們在構建復雜對象的時候,我們如果發現每個部分可能都是變化的,并且是多個不同的構建步驟的時候,我們可以考慮使用創建者模式。相比我們之前講述的工廠和抽象工廠模式區別還是很大的,我們發現創建者適合這類復雜對象的創建,對于抽象工廠可能就無法完成這樣的組裝工作,而且創建者模式是把復雜對象的內部創建方法進行調用,組織協調了對象的各個部分前后順序的控制。簡單的描述創建者就是這樣的情況:
[](http://images.cnblogs.com/cnblogs_com/hegezhou_hot/Windows-Live-Writer/633b606b0863_B56F/image_13.png)
由于本人水平有限,或者講述能力有限,表達思路錯誤或者想法錯誤,請大家批評指出,如果您有更好的意見或者想法,請提出討論,歡迎大家提出寶貴意見和建議。
### 七、系列進度。
創建型>
1、[系統架構技能之設計模式-單件模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/10/02/1841390.html)
2、[系統架構技能之設計模式-工廠模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/11/30/1892227.html)
3、[系統架構技能之設計模式-抽象工廠模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/12/01/1893388.html)
4、[系統架構技能之設計模式-創建者模式](http://www.cnblogs.com/hegezhou_hot/archive/2010/12/02/1894771.html)
5、系統架構技能之設計模式-原型模式
結構型>
1、系統架構技能之設計模式-組合模式
2、系統架構技能之設計模式-外觀模式
3、系統架構技能之設計模式-適配器模式
4、系統架構技能之設計模式-橋模式
5、系統架構技能之設計模式-裝飾模式
6、系統架構技能之設計模式-享元模式
7、系統架構技能之設計模式-代理模式
行為型>
1、系統架構技能之設計模式-命令模式
2、系統架構技能之設計模式-觀察者模式
3、系統架構技能之設計模式-策略模式
4、系統架構技能之設計模式-職責模式
5、系統架構技能之設計模式-模板模式
6、系統架構技能之設計模式-中介者模式
7、系統架構技能之設計模式-解釋器模式
### 八、下篇預告。
下篇將會針對原型模式進行講述,該模式也是創建型模式中很有特點設計模式之一,該 模式是利用現有的一個對象進行克隆的過程產生一個新的對象,當然這里的復制對象可以是2種,深復制和淺復制,在這個系列的總結中如果您有好的想法或者創意,請提出來,希望大家多提寶貴意見,錯誤之處還請指出,請大家繼續支持。