1. 程式人生 > >創建型模式篇(工廠模式Factory Pattern)

創建型模式篇(工廠模式Factory Pattern)

sel case create png image eventlog ole 擁有 其他

一、工廠模式(Factory Pattern)

1、定義:  在軟件系統,經常面臨著“某個對象”的創建工作,由於需求的變化,這個對象的具體實現經常面臨著劇烈的變化,但是它卻擁有比較穩定的接口。提供一種封裝機制來隔離這個對象的變化,從而保持系統中其他依賴這個變化對象的對象,就要用到工廠模式。

2、目的:定義一個用戶創建對象的接口,讓子類決定實例化哪一個類,FactoryMethod使一個類的實例化延遲到它的子類。

3、結構圖:

技術分享圖片

工廠模式:定義一個用於創建對象的接口,但是讓子類決定實例化哪個類。也就是說在工廠模式中,核心的工廠類不在負責所有產品的創建,而是將具體創建工作交給它的子類去做。這個核心類僅僅負責給出具體工廠必須實現的接口,而不用接觸哪一個產品類被實例化這種細節。

現實工作中的例子:

//設計日誌記錄類Log,支持記錄的方法有FileLog和EventLog兩種記錄類型。
//不用設計模式來實現:
public class Log
{
    public void WriteEvent()
    {
        Console.WriteLine("EventLog Success!");
    }
    public void WriteFile()
    {
        Console.WriteLine("FileLog Success!");
    }
    public void Write(string LogType)
    {
        
switch(LogType.ToLower()) { case "event": WriteEvent(); break; case "file": WriteFile(); break; default: break; } } }
//這樣程序結構顯然不符合我們要求,加入要增加一種新的日誌類型DataBaseLog,那麽就要修改Log類,重新加入 //switch語句不斷在變化,這就引起了整個應用程序的不穩定,EventLog和FileLog是兩種完全不同的記錄方式 //他們之前不存在必然的聯系,應該把他們分別作為單獨的對象來處理對待

使用工廠模式來實現:

思想是為EventLog和FileLog抽象出一個共同的父類,結構圖如下:

技術分享圖片

//首先抽象一個父類Log
public abstact class Log
{
    public abstract void Write();
}
//讓EventLog和FileLog去繼承父類,重寫父類裏的方法
//EventLog類
public class EventLog:Log
{
    public override void Write()
    {
        Conosole.WriteLine("EventLog Write Success!");
    }
}
//FileLog類
public class FileLog:Log
{
    public override void Write()
    {
        Console.WriteLine("FileLog Write Success!");
    }
}
//現在再有一個新的日誌記錄方式DataBaseLog時候,只需要增加一個DataBaseLog子類去繼承父類就可以
//不用去修改EventLog和FileLog類,滿足了類之間的層次關系,又很好的符合面向對象設計中的
//單一職責原則,每一個類都只負責一件具體的事情。
//但是我們並不確定客戶程序去調用哪一種日誌記錄方式
//也許會用到下面的語句:
EventLog eventLog=new EventLog();
eventLog.Write();
//當日誌記錄方式從EventLog變成FileLog時候,我們就要修改程序中上面的創建對象語句。
//這樣的工作量可想而知,此時就需要解耦具體的日誌記錄方式,就可以引入工廠模式了
//每一個日誌記錄的對象就是工廠所生成的產品,既然有兩種記錄方式,那就需要兩個不同的工廠去生產。

因此聲明兩個不同類型的工廠類:EventFactory類和FileFactory類

//EventFactory類
public class EventFactory
{
    public EventLog Create()
    {
        return new EventLog();
    }
}
//FileFactory類
public class FileFactory
{
    public FileFactory Create()
    {
        return new FileLog();
    }
}

這兩個工廠和具體的產品之間是平行的結構,並且一一對應,我們在他們兩個基礎上抽象出一個公用的接口:技術分享圖片

//LogFactory類
public abstract class LogFactory
{
    public abstract Log Create();
}

//EventFactory類
public class EventFactory:LogFactory
{
    public override EventLog Create()
    {
        return new EventLog();
    }
}
//FileFactory類
public class FileFactory:LogFactory
{
    public override FileFactory Create()
    {
        return new FileLog();
    }
}
//這樣通過工廠模式,把上面對象創建工作封裝在了工廠中,達到了具體應用程序
//和具體日誌記錄方式對象之間的解耦
//客戶端調用代碼
publc class Test
{
    public static void Main(string[] args)
    {
        LogFactory factory=new EventFactory();
        Log log=factory.Create();
        log.Write();
    }
}

在應用程序中,Log對象創建是頻繁的,要是換成另一種日誌記錄方式,只需要修改為:

LogFactory factory=new FileFactory()

其他任何地方都不需要修改,我們也可以說個.net的特性,避免這種不必要的修改,利用.net的反射機制來進行實現,所以就要用到配置文件了,如果我們想用哪一種日誌記錄方式,就在相應的配置文件中設置如下:

<appSettings>
    <add key="factoryName" value="EventFactory"></add?
</appSettings>

然後客戶端代碼可以這樣寫:

//客戶端調用代碼
publc class Test
{
    public static void Main(string[] args)
    {
        string strFactoryName=ConfigurationSettings.AppSettings["factoryName"];//引入配置文件
        LogFactory factory;
        factory=(LogFactory)Assembly.Load("FactoryMethod").CreateInstance("FactoryMethod"+strFactoryName);
        Log log=factory.Create();
        log.Write();
    }
}

創建型模式篇(工廠模式Factory Pattern)