設計模式培訓之二:簡單工廠、工廠方法


查看本人文章索引請通過http://www.cnblogs.com/seesea125/archive/2012/04/17/2453256.html

一、簡單工廠和工廠方法定義:

簡單工廠模式是由一個工廠類根據參數來決定創立出哪一種產品類的實例。

工廠方法模式通過調用不同的方法返回需要的類,而不是去實例化具體的類。 對實例創建進行了包裝。 工廠方法是一組方法, 他們針對不同條件返回不同的類實例,這些類一般有共同的父類。

工廠方法模式實施一種按需分配的策略, 即傳入參數進行選擇, 工廠方法根據參數進行選擇,返回具體的實例。

 

二、實例講解:實現加減乘除

程序需求:

處理兩個數的+,-,*,/等運算

 

1. 是面向過程的實現方法:

string strResult = "";
            switch (Operate)
            {
                case "+":
                    strResult = Convert.toString(Convert.ToDouble(NumA) + Convert.ToDouble(NumB));
                    break;
                case "-":
                    strResult = Convert.toString(Convert.ToDouble(NumA) - Convert.ToDouble(NumB));
                    break;
                case "*":
                    strResult = Convert.toString(Convert.ToDouble(NumA) * Convert.ToDouble(NumB));
                    break;
                case "/":
                    if (NumB != 0)
                    {
                        strResult = Convert.toString(Convert.ToDouble(NumA) + Convert.ToDouble(NumB));
                    }
                    else
                    {
                        strResult = "除數不能為0";
                    }
                    break;
            }

當增加需求時,例如:增加開方運算,這時我們需要更改上面switch的代碼。如果再增加需求,還要更改switch代碼。這樣的代碼很難維護。

健壯的設計應該是易擴展,不修改原有代碼(或盡量減少修改原有代碼)。

應對變化的運算方式,簡單工廠就是一個很簡單,好用的模式,下面是簡單工廠的實現

 

2. 用簡單工廠實現:

ULM圖:

sclip_image002

public abstract class Operation
{
    public double NumA { get; set; }
    public double NumB { get; set; }
    public abstract double GetResult();
}

public class OperationAdd : Operation
{
    public override double GetResult()
    {
        return NumA + NumB;
    }
}

public class OperationSub : Operation
{
    public override double GetResult()
    {
        return NumA - NumB;
    }
}

工廠類:

public class Factory
{
    public Operation Create(string ope)
    {
        Operation operation=null;
        switch(ope)
        {
        case "+":
        operation=new OperationAdd();
        break;
        case "-":
        operation=new OperationSub();
        break;
        }
        return operation;
    }
}

 

客戶端調用:

Operation oper;

oper=new Factory().Create("+");
oper.NumA=1;
oper.NumB=2;
double result=oper.GetResult();

這時在客戶端代碼就沒有switch代碼,現在的switch代碼也沒有運算邏輯。運算邏輯在GetResult()方法中。

當再有新需求時,我就可以增加子類(繼承自Operation),在子類的GetResult方法中設置運算規則。現在只需在switch中增加一個case返回增加子類實例的代碼。

簡單工廠是一個不完美的模式,因為它還是修改了switch代碼。

 

3 用工廠方法實現:

應對上面的需求也可以使用工廠方法模式,工廠方法使一個類的實例化延遲到其子類。

UML圖:

clip_image004

    public interface IFactory
    {
        Operation Create();
    }
    public class AddOperation : IFactory
    {
        public Operation Create()
        {
            return new OperationAdd();
        }
    }
    public class SubOperation : IFactory
    {
        public Operation Create()
        {
            return new OperationSub();
        }
    }

    public abstract class Operation
    {
        public double NumA { get; set; }
        public double NumB { get; set; }
        public abstract double GetResult();
    }
    public class OperationAdd : Operation
    {
        public override double GetResult()
        {
            return NumA + NumB;
        }
    }
    public class OperationSub : Operation
    {
        public override double GetResult()
        {
            return NumA - NumB;
        }
    }

 

客戶端:

IFactory factory = new AddOperation();
Operation oper = factory.Create();
oper.NumA = 3;
oper.NumB = 2;
double result = oper.GetResult();

 

在客戶程序中,我們有效地避免了具體產品對象和應用程序之間的耦合,可是我們也看到,增加了具體工廠對象和應用程序之間的耦合。

當我們由加號操作變成減號操作時,只需要改動一處就可以了,其他地方都不用改。

IFactory factory = new SubOperation();
Operation oper = factory.Create();
oper.NumA = 3;
oper.NumB = 2;
double result = oper.GetResult();

 

當然這樣的話,我們還是改動代碼,這時候可以利用.NET反射機制來消除它,這樣改動時,只需要改動配置文件就可以了

<appSettings>
  <add key="factoryName" value="AddOperation"></add>
</appSettings>

客戶端代碼:

string factoryName = ConfigurationSettings.AppSettings["factoryName"];
 IFactory factory = (IFactory)Assembly.Load("BLL").CreateInstance("BLL." + factoryName);
Operation oper = factory.Create();
oper.NumA = 3;
oper.NumB = 2;
double result = oper.GetResult();


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM