- 創建型模式
這些設計模式提供了一種在創建對象的同時隱藏創建邏輯的方式,而不是使用 new 運算符直接實例化對象。這使得程序在判斷針對某個給定實例需要創建哪些對象時更加靈活。
- 分類
- 工廠模式(Factory Pattern)
- 抽象工廠模式(Abstract Factory Pattern)
- 單例模式(Singleton Pattern)
- 建造者模式(Builder Pattern)
- 原型模式(Prototype Pattern)
- 工廠模式(Factory Pattern)
定義一個創建對象的接口,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。
C#: public abstract class Product //抽象產品類
{
public abstract void method(); //抽象方法
}
public class ConcreteProduct:Product //具體產品類
{
public override void method()
{
//業務邏輯處理
}
}
public class Factory //工廠類
{
//根據類名創建對象
public Product GetProduct(String name)
{
if (name.Equals("ConcreteProduct", StringComparison.CurrentCultureIgnoreCase)) return new ConcreteProduct();
return null;
}
//根據類型創建對象
public static Product getProduct(Type type)
{
//判斷type是否繼承了Shape接口
if (typeof(Product).IsAssignableFrom(type))
return (Product)Activator.CreateInstance(type);
return null;
}
}
public class Client //場景類
{
public static void Main(string[] args)
{
Factory factory = new Factory();
Product p1 = factory.GetProduct("concreteproduct");
Product p2 = Factory.getProduct(typeof(ConcreteProduct));
}
}
優點: 1、一個調用者想創建一個對象,只要知道其名稱就可以了。
2、擴展性高,如果想增加一個產品,只要擴展一個工廠類就可以。
3、屏蔽產品的具體實現,調用者只關心產品的接口。
缺點:每次增加一個產品時,都需要增加一個具體類和對象實現工廠,使得系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴。這並不是什麼好事。
注意事項:作爲一種創建類模式,在任何需要生成複雜對象的地方,都可以使用工廠方法模式。有一點需要注意的地方就是複雜對象適合使用工廠模式,而簡單對象,特別是只需要通過 new 就可以完成創建的對象,無需使用工廠模式。如果使用工廠模式,就需要引入一個工廠類,會增加系統的複雜度。
- 抽象工廠模式(Abstract Factory Pattern)
提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
public interface IProduct
{
public void method1();
}
public abstract class AbstractProduct1:IProduct
{
public abstract void method2();
}
public abstract class AbstractProduct2 : IProduct
{
public abstract void method2();
}
public class ConcreteProduct1 : AbstractProduct1
{
public override void method2()
{
//業務邏輯處理
}
public void method1()
{
//業務邏輯處理
}
}
public class ConcreteProduct2 : AbstractProduct2
{
public override void method2()
{
//業務邏輯處理
}
public void method1()
{
//業務邏輯處理
}
}
public abstract class AbstractFactory
{
//有幾個產品簇的工廠就有幾個實現方法
public abstract AbstractProduct1 GetProduct1(string name);
public abstract AbstractProduct2 GetProduct2(string name);
}
public class Factory1:AbstractFactory
{
//根據類名創建對象
public override AbstractProduct1 GetProduct1(String name)
{
if (name.Equals("ConcreteProduct1", StringComparison.CurrentCultureIgnoreCase)) return new ConcreteProduct1();
return null;
}
}
public class Factory2 : AbstractFactory
{
//根據類名創建對象
public override AbstractProduct2 GetProduct2(String name)
{
if (name.Equals("ConcreteProduct2", StringComparison.CurrentCultureIgnoreCase)) return new ConcreteProduct2();
return null;
}
}
public class FactoryCreator //創建工廠的類
{
//根據類名創建對象
public static AbstractFactory GetFactory(String name)
{
if (name.Equals("Factory1", StringComparison.CurrentCultureIgnoreCase)) return new Factory1();
if (name.Equals("Factory2", StringComparison.CurrentCultureIgnoreCase)) return new Factory2();
return null;
}
}
public class Client
{
public static void Main(string[] args)
{
//AbstractFactory factory1 = new Factory1();
//AbstractFactory factory2 = new Factory2();
AbstractFactory factory1 = FactoryCreator.GetFactory("Factory1");
AbstractFactory factory2 = FactoryCreator.GetFactory("Factory2");
ConcreteProduct1 p1 = factory1.GetProduct1("concreteproduct1") as ConcreteProduct1;
ConcreteProduct2 p2 = factory2.GetProduct2("concreteproduct2") as ConcreteProduct2;
}
}
優點:當一個產品族中的多個對象被設計成一起工作時,它能保證客戶端始終只使用同一個產品族中的對象。
缺點:產品族擴展非常困難,要增加一個系列的某一產品,既要在抽象的 Creator 里加代碼,又要在具體的裏面加代碼。
注意事項:產品族難擴展(改動太大,不符合開閉原則),產品等級易擴展。
- 單例模式(Singleton Pattern)
保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
c# public class Singleton
{
private static Singleton instance = new Singleton();
private Singleton() { }
public static Singleton Instance
{
get
{
return instance;
}
}
public void ShowMessage()
{
Console.WriteLine("this is a singleObject");
}
}
public class Client
{
static void Main(string[] args)
{
Singleton.Instance.ShowMessage();
}
}
優點: 1、在內存裏只有一個實例,減少了內存的開銷,尤其是頻繁的創建和銷燬實例(比如管理學院首頁頁面緩存)。
2、避免對資源的多重佔用(比如寫文件操作)。
缺點:沒有接口,不能繼承,與單一職責原則衝突,一個類應該只關心內部邏輯,而不關心外面怎麼樣來實例化。
注意事項:getInstance() 方法中需要使用同步鎖 synchronized (Singleton.class) 防止多線程同時進入造成 instance 被多次實例化。當前是線程不安全的。
- 建造者模式(Builder Pattern)
建造者模式(Builder Pattern)使用多個簡單的對象一步一步構建成一個複雜的對象。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
一個 Builder 類會一步一步構造最終的對象。該 Builder 類是獨立於其他對象的。
public class Product
{
public void doSomething()
{
//獨立業務處理
}
}
public abstract class Builder
{
public abstract void setPart();//設置產品的不同部分,以獲得新的產品
public abstract Product buildProduct();//建造產品
}
public class ConcreteBuilder:Builder
{
private Product product = new Product();
//設置產品零件
public override void setPart()
{
//產品類內的邏輯處理
}
//組建一個產品
public override Product buildProduct()
{
return product;
}
}
public class Director
{
private Builder builder = new ConcreteBuilder();
//構建不同的產品
public Product getAProduct()
{
builder.setPart();
//設置不同的零件,產生不同的產品
return builder.buildProduct();
}
}
public class Client
{
static void Main(string[] args)
{
Director director = new Director();
Product product = director.getAProduct();
}
}
優點: 1、建造者獨立,易擴展。
2、便於控制細節風險。
缺點: 1、產品必須有共同點,範圍有限制。
2、如內部變化複雜,會有很多的建造類。
使用場景: 1、需要生成的對象具有複雜的內部結構。 2、需要生成的對象內部屬性本身相互依賴。
注意事項:與工廠模式的區別是:建造者模式更加關注與零件裝配的順序。與模版方法模式結合使用更佳(產品類中使用模版方法)
- 原型模式(Prototype Pattern)
用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。
原型模式(Prototype Pattern)是用於創建重複的對象,同時又能保證性能。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
這種模式是實現了一個原型接口,該接口用於創建當前對象的克隆。當直接創建對象的代價比較大時,則採用這種模式。例如,一個對象需要在一個高代價的數據庫操作之後被創建。我們可以緩存該對象,在下一個請求時返回它的克隆,在需要的時候更新數據庫,以此來減少數據庫調用。
public class Client
{
static void Main(string[] args)
{
Prototype pt1 = new Prototype();
Prototype pt2 = (Prototype)pt1.Clone();
Console.WriteLine(pt2.name);
}
}
public class Prototype : ICloneable //實現接口
{
public string name = "ssss";
public object Clone()
{
object obj = null;
try
{
obj = this.MemberwiseClone();//淺拷貝
}
catch (Exception e)
{
Console.WriteLine(e.Message);
//異常處理
}
return obj;
}
}
優點: 1、性能提高。 2、逃避構造函數的約束。
缺點: 1、配備克隆方法需要對類的功能進行通盤考慮,這對於全新的類不是很難,但對於已有的類不一定很容易,特別當一個類引用不支持串行化的間接對象,或者引用含有循環結構的時候。 2、必須實現 ICloneable 接口。
使用場景: 1、資源優化場景。 2、類初始化需要消化非常多的資源,這個資源包括數據、硬件資源等。 3、性能和安全要求的場景。 4、通過 new 產生一個對象需要非常繁瑣的數據準備或訪問權限,則可以使用原型模式。 5、一個對象多個修改者的場景。 6、一個對象需要提供給其他對象訪問,而且各個調用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調用者使用。 7、在實際項目中,原型模式很少單獨出現,一般是和工廠方法模式一起出現,通過 clone 的方法創建一個對象,然後由工廠方法提供給調用者。
注意事項:與通過對一個類進行實例化來構造新對象不同的是,原型模式是通過拷貝一個現有對象生成新對象的。淺拷貝實現 ICloneable,重寫,深拷貝是通過實現 Serializable 讀取二進制流。