- 創建型模式
- 簡單工廠模式
- 工廠方法模式
- IOC與工廠方法模式的結合
- 泛型工廠
- 委托工廠
創建型模式
創建型模式可以隔離客戶程式對需要實體化型別的依賴關系,這類模式一般通過將實體化具體物件的職責委托給第三方物件的方式,使得客戶程式或者外部系統在獲得所需的具體型別實體的同時,而不必對其發生直接的參考,
創建型模式包括:
- 工廠方法模式
- 單例模式
- 抽象工廠模式
- 創建者模式
- 原型模式
按照大多數設計模式書籍采用的順序,首先從工廠方法模式開始,
簡單工廠模式
簡單工廠模式并沒有被歸入23種設計模式之列,但可以作為學習工廠方法模式前的預備,簡單工廠模式在管理物件創建方面,提供的是最簡單的方案,它僅僅簡單的對不同類物件的創建進行了一層薄薄的封裝,客戶程式在使用時,通過向簡單工廠傳遞一個型別來指定要創建的物件,其UML類圖如下:

Client需要的是具體的產品ConcreteProductA或者ConcreteProductB,如果直接new()就會依賴物件實體,引入簡單工廠后,Client變成了依賴IProduct和SampleFactory,
代碼示例:
//產品介面
public interface IProduct { };
//具體產品
public class ConcreteProductA : IProduct { }
public class ConcreteProductB : IProduct { }
public enum Category { A, B }
//簡單工廠
public class SampleFactory
{
public IProduct Create(Category category)
{
switch (category)
{
case Category.A:
return new ConcreteProductA();
case Category.B:
return new ConcreteProductB();
default:
throw new ArgumentOutOfRangeException();
}
}
}
呼叫:
[Test]
public void SampleFactoryTest()
{
SampleFactory sampleFactory = new SampleFactory();
IProduct product = sampleFactory.Create(Category.A);
Assert.AreEqual(product.GetType(), typeof(ConcreteProductA));
}
工廠方法模式
簡單工廠模式中的工廠負責生產所有的產品型別,但如果工廠負責生產的產品只有一種,就可以進一步抽象了,這便出現了工廠模式,
GOF對工廠方法模式的描述是:
Define an interface for creating an object, but let subclasses decide which class toinstantiate. Factory Method lets a class defer instantiation to subclasses..
— Design Patterns : Elements of Reusable Object-Oriented Software
工廠方法模式定義了一個抽象的工廠,它的子類物體工廠都有統一通用的工廠方法,用來生產具體的產品,這樣就把類的實體化延遲到其子類,
工廠方法主要有四個角色:
- 抽象產品型別(Product),工廠要加工的物件所具有的抽象特征物體,
- 具體產品型別(Concrete Product),實作客戶程式所需要的抽象特質的型別,它就是工廠需要延遲實體的備選物件,
- 抽象工廠型別(IFactory),定義一個工廠方法的默認實作,它回傳抽象產品型別,
- 具體工廠型別(Concrete Factory):重新定義了產品創建程序,回傳具體產品型別,
UML類圖

代碼示例:
//抽象產品型別
public interface IProduct
{
string Name { get; } //抽象產品所必須具有的特征
}
//具體產品型別
public class ProductA : IProduct
{
public string Name { get { return "A"; } }
}
public class ProductB : IProduct
{
public string Name { get { return "B"; } }
}
//抽象工廠型別
public interface IFactory
{
IProduct Create(); //抽象的工廠描述
}
//具體工廠型別
public class FactoryA : IFactory
{
public IProduct Create()
{
return new ProductA();
}
}
public class FactoryB : IFactory
{
public IProduct Create()
{
return new ProductB();
}
}
呼叫:
public class Client1
{
public void SomeMethod()
{
IFactory factory = new FactoryA();
IProduct product = factory.Create();
}
}
客戶程式需要使用IProduct的時候,只需要獲取到IFactory,通過呼叫其統一制定的Create()方法就可以獲取到具體的產品,具體需要哪個產品由Factory決定,這樣就隔離了客戶程式對具體產品的依賴,但這里還有個問題是在獲取IFactory的時候需要初始化具體的工廠,這樣就對具體的工廠產生了依賴,
IOC與工廠方法模式的結合
為了解決上述問題,可以把IFactory作為客戶程式的引數,然后采用依賴注入的方式將具體的工廠注入:
public class Client2
{
private IFactory factory;
public Client2(IFactory factory)
{
this.factory = factory;
}
public string SomeMethod()
{
IProduct product = factory.Create();
return product.Name;
}
}
這樣客戶程式就變成了真正地只依賴IFactory和IProduct了,但問題是不論采用哪種依賴注入框架,都需要注冊介面與實體的映射關系,那么這種方式就只是相當于把對具體產品的依賴“甩”到了“客戶程式的客戶程式”,怎么辦呢,退無可退的時候,考慮把介面與實體的映射關系放到組態檔吧,
泛型工廠
上面的工廠方法模式中,每個具體的工廠負責生產一種產品,且都實作了抽象工廠的Create()方法,于是借助泛型可以實作進一步的抽象:
public interface IFactory<T>
{
T Create(); //抽象的工廠描述
}
public abstract class FactoryBase<T> : IFactory<T> where T : new()
{
public virtual T Create()
{
return new T();
}
}
public class ProductAFactory : FactoryBase<ProductA> {
public override ProductA Create(){
return new ProductA();
}
}
public class ProductBFactory : FactoryBase<ProductB> { }
在抽象工廠和具體的工廠之間增加了支持泛型的FactoryBase,在這里實作了通用的Create()方法,如果某個具體工廠需要特殊的Create流程,只需重寫虛方法即可,這樣在工廠種類比較多而流程有大多相同的情況下,可以減少很多代碼,
委托工廠
前面代碼中的工廠生產的產品都是物件,如果需要生產的是方法呢,C#的委托機制可以方便地滿足這種需求,
委托的本質是方法的指標,是對一類方法的抽象,所以委托本身就可以作為抽象產品的定義,而與委托簽名一致的方法就是具體產品了,
代碼示例:
public delegate int CalculateHandler(params int[] items);
public class Calculator
{
public int Add(params int[] items)
{
int result = 0;
foreach (var item in items)
{
result += item;
}
return result;
}
public int Multi(params int[] items)
{
int result = 1;
foreach (var item in items)
{
result *= item;
}
return result;
}
}
public class AddHandlerFactory : IFactory<CalculateHandler>
{
public CalculateHandler Create()
{
return new Calculator().Add;
}
}
public class MultiHandlerFactory : IFactory<CalculateHandler>
{
public CalculateHandler Create()
{
return new Calculator().Multi;
}
}
呼叫:
[Test]
public void CalculateHandlerTest()
{
CalculateHandler addHandler = new AddHandlerFactory().Create();
Assert.AreEqual(1 + 2 + 3, addHandler(1, 2, 3));
CalculateHandler multiHandler = new MultiHandlerFactory().Create();
Assert.AreEqual(1 * 2 * 3, multiHandler(1, 2, 3));
}
參考書籍:
王翔著 《設計模式——基于C#的工程化實作及擴展》
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/4538.html
標籤:設計模式
上一篇:命令模式
下一篇:設計模式(2) 單例模式
