一、簡單工廠模式 簡單工廠模式,提供了一種創建對象的便捷方法。創建者通過不同的類型參數,創建相對應的對象。 實現代碼如下: 優點: 在創建固定類型的對象時,比較簡單好用。 缺點: 1. 在添加對象類型時,需要更改Creator類裡面的函數,違反了軟體設計中的開閉原則。 2. Creator類依賴於具 ...
一、簡單工廠模式
簡單工廠模式,提供了一種創建對象的便捷方法。創建者通過不同的類型參數,創建相對應的對象。
實現代碼如下:
public class Product { public virtual void Funtion() {} } public class ProductA : Product { public override void Funtion() { base.Funtion(); } } public class ProductB : Product { public override void Funtion() { base.Funtion(); } } public class Creator { public static Product Create(string type) { switch (type) { case "A": return new ProductA(); case "B": return new ProductB(); default: return null; } } } class Program { static void Main(string[] args) { Product pa = Creator.Create("A"); } }
優點:
在創建固定類型的對象時,比較簡單好用。
缺點:
1. 在添加對象類型時,需要更改Creator類裡面的函數,違反了軟體設計中的開閉原則。
2. Creator類依賴於具體類ProductA,和ProductB,在具體類變化時直接影響Creator類,耦合性過強。
工廠模式
工廠模式將對象的創建延遲到了具體的子類裡面實現。這樣,我們創建子類對象時,不需要知道具體的子類,只需獲取到相應的類型的工廠即可。同時,工廠模式消除了簡單工廠方法所具有高耦合性,且滿足軟體的設計原則。
工廠模式,解決了創建多個、同類對象的複雜問題。比如我們需要創建100個ProductA種類的對象,如果不使用工廠模式,我們需要new出100個ProductA對象來;通過工廠模式,只需要調用FactoryA多次就能夠完成對象的創建。
1. 實現方法
1)工廠模式最常用的結構類圖:
實現代碼(C#)如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Factory { public class Product { public virtual void Funtion() { } } public class ProductA : Product { public override void Funtion() { base.Funtion(); } } public class ProductB : Product { public override void Funtion() { base.Funtion(); } } public class Factory { virtual public Product Create() { return null; } } public class FacotryA : Factory { public override Product Create() { return new ProductA(); } } public class FactoryB : Factory { public override Product Create() { return new ProductB(); } } class FactoryMode { static void Main(string[] args) { FacotryA fa = new FacotryA(); FactoryB fb = new FactoryB(); Product pa = fa.Create(); Product pb = fb.Create(); } } }
工廠模式的問題在於,每添加一種新的Product必須添加與之相對應的Factory類。比如,現在需要增加一種對象ProductC,同時需要添加FactoryC類來創建ProductC的對象。這樣的話,如果需要添加N多種對象,同時就必須添加與之對應的N種工廠類,增加了編碼量和繁瑣程度,如下圖。
2)使用類模板
在需要添加多種對象時,採用模版的方式,可以避免創建過多的工廠子類。
此處,只需要定義一個類模板template<class TheProduct> ConcreteFactoy,只要是從Product基類派生的對象類型,都可以通過這個類模板實現。
以下是實現代碼(C++).
#include "stdafx.h" #include <iostream> using namespace std; class Product { public: virtual void Function() = 0; }; class ProductA : public Product { public: void Function(); }; void ProductA::Function() { cout << "Create ProductA..." << endl; } class Factory { public: virtual Product* Create() = 0; }; template<class TheProduct> class ConcreteFactroy : public Factory { public: virtual Product* Create(); }; template<class TheProduct> Product* ConcreteFactroy<TheProduct>::Create() { return new TheProduct; } int _tmain(int argc, _TCHAR* argv[]) { ConcreteFactroy<ProductA> MyFactory; Product* pa = MyFactory.Create(); pa->Function(); return 0; }
3. 抽象工廠
抽象工廠模式,用於創建一組相關或獨立的對象。通過此模式,用戶不需要知道具體的對象類型,只需找到創建的工廠類即可。抽象工廠與工廠方法的區別主要如下:
工廠方法中的工廠類只能創建一種對象,如FactoryA -> ProductA。
抽象工廠中的工廠類可以創建多種類型的對象, Factory1 -> {product1, product2, …,productN}
抽象工廠的問題在於,當我們需要添加新的對象AbstractProductC時,需要同時修改AbstractFactory, ConcreteFactory1和ConcreteFactory2三個類。從這個角度來看,添加新類型的對象時,與簡單工廠模式類似。這裡,我們不妨就先把抽象工廠更改為簡單工廠模式,然後再通過反射機制進行改進。通過反射,用戶只需要傳遞product子類型的名字給Factory類。Factory類根據傳入的類名字,生成類對象。無論後期添加多少種對象,都不用再添加對應的工廠類。
以下描述了,抽象工廠模式訪問資料庫,然後更改為簡單工廠模式,再使用反射機制的整個過程(摘自《大話設計模式》)。(其實,三種工廠模式都可以使用反射機制來簡化對象生成的過程。)
使用抽象工廠訪問資料庫的類圖:
我們將抽象工廠更改為簡單工廠模式,如下:
使用反射實現(C#),如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; namespace AbstractFactory { public interface IUser { void InsertUser(IUser user); IUser GetUser(string user); } public class SQLUser : IUser { public void InsertUser(IUser user) { Console.WriteLine("Access user"); } public IUser GetUser(string user) { return null; } } public class AccessUser : IUser { public void InsertUser(IUser user) { Console.WriteLine("Access user"); } public IUser GetUser(string user) { return null; } } public class DataAccess { private readonly string dbType = "SQL"; public IUser CreateUser() { IUser result = null; switch (dbType) { case "SQL": result = new SQLUser(); break; case "Access": result = new AccessUser(); break; default: break; } return result; } public string ReflectType { get; set; } public IUser CreateUserByReflection() { //(IUser)Assembly.Load(當前程式集的名稱 "Factory").CreateInstance("命名空間.類名"); return (IUser)Assembly.Load("Factory").CreateInstance(ReflectType); } } class AbstractFactory_Reflect { static void Main(string[] args) { DataAccess da = new DataAccess(); da.ReflectType = "AbstractFactory.SQLUser"; IUser user = null; user = da.CreateUserByReflection(); SQLUser sqlUser = user as SQLUser; if (sqlUser == null) { Console.WriteLine("NULL..."); } } } }