引言
上一篇介紹了設計模式中的簡單工廠模式-C#設計模式(2)-簡單工廠模式,本篇將介紹工廠方法模式,在簡單工廠模式下進行改造;
工廠方法模式簡介
工廠方法(FactoryMethod)模式:定義一個用於創建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類中;
上一篇簡單工廠模式中講到了其缺點,工廠類集中了所有產品創建邏輯的,如果不能正常工作的話會對系統造成很大的影響。如果我們增加一個產品,我們就需要在工廠類中增加case分支條件,修改原有的類,這樣我們不但對擴展開放了,也對修改開放了,違背了“開放-封閉”原則,所以我們對簡單工廠模式進行優化,對工廠抽出一個接口,就有了以下的工廠方法模式
結構圖
(來自大話設計模式)
應用實例
這里實例依然采用上一篇中的實例:現在市面上很多種數據庫,Oracle、SqlSever、Mysql等;比如我們現在需要寫一個通用的數據處理,如新增、更新等操作,能夠達到切換任意一個數據庫,都能夠調用對應版本數據庫的的新增或者更新操作;
下面的類圖、代碼將均以數據庫操作為實例;
類圖
代碼實例
注:這里實例僅做示例,不包含業務邏輯;
創建數據操作抽象類
以新增、更新為例;
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FactoryMethod { /// <summary>
/// 數據庫操作抽象類 /// </summary>
public abstract class AbstractDataBaseOpr { /// <summary>
/// 新增 /// </summary>
public abstract bool Insert(); /// <summary>
/// 更新 /// </summary>
/// <returns></returns>
public abstract bool Update(); } }
Oracle數據操作類
繼承上述數據庫操作抽象類

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FactoryMethod { /// <summary>
/// oracle操作 /// </summary>
public class OracleDbOpr : AbstractDataBaseOpr { /// <summary>
/// 新增 /// </summary>
public override bool Insert() { Console.WriteLine("Oracle新增記錄"); return true; } /// <summary>
/// 更新 /// </summary>
/// <returns></returns>
public override bool Update() { Console.WriteLine("Oracle更新記錄"); return true; } } }
SqlServer數據操作類
繼承上述數據庫操作抽象類

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FactoryMethod { /// <summary>
/// sqlServer操作 /// </summary>
public class SqlServerDbOpr : AbstractDataBaseOpr { /// <summary>
/// 新增 /// </summary>
public override bool Insert() { Console.WriteLine("SqlServer新增記錄"); return true; } /// <summary>
/// 更新 /// </summary>
/// <returns></returns>
public override bool Update() { Console.WriteLine("SqlServer更新記錄"); return true; } } }
創建DB工廠接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FactoryMethod { /// <summary>
/// DB工廠接口 /// </summary>
public interface IDbFactory { /// <summary>
/// 創建db操作實例 /// </summary>
/// <returns></returns>
AbstractDataBaseOpr CreateDbOpr(); } }
Oracle工廠類
實現接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FactoryMethod { /// <summary>
/// oracle db工廠 /// </summary>
public class OracleDbFactory : IDbFactory { /// <summary>
/// 創建數據庫操作實例 /// </summary>
/// <returns></returns>
public AbstractDataBaseOpr CreateDbOpr() { return new OracleDbOpr(); } } }
SqlServer工廠類
實現接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FactoryMethod { /// <summary>
/// SqlServer db工廠 /// </summary>
public class SqlServerDbFactory : IDbFactory { /// <summary>
/// 創建數據庫操作實例 /// </summary>
/// <returns></returns>
public AbstractDataBaseOpr CreateDbOpr() { return new SqlServerDbOpr(); } } }
業務調用
oracle數據庫和sqlserver數據庫操作分別調用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FactoryMethod { class Program { static void Main(string[] args) { //oracle操作
IDbFactory dbFactory1 = new OracleDbFactory(); AbstractDataBaseOpr opr1 = dbFactory1.CreateDbOpr(); opr1.Insert(); opr1.Update(); Console.WriteLine("-----------------------------------------"); //切換為sqlserer
IDbFactory dbFactory2 = new SqlServerDbFactory(); AbstractDataBaseOpr opr2 = dbFactory2.CreateDbOpr(); opr2.Insert(); opr2.Update(); Console.ReadKey(); } } }
調用結果
優缺點
優點
- 用戶只需要關心所需產品對應的工廠,不需要關注如何創建。
- 在增加新產品時,需要增加新的產品類及對應的工廠類,不會影響其它產品,符合開閉原則。
缺點
當需要增加新產品的時候,需要增加新的產品類,還需要增加對應的工廠類