簡單工廠、工廠方法和抽象工廠模式

iDotNetSpace發表於2009-04-14

假想場景:hp和apple是全球知名的電腦生產廠家,他們各自的電腦

作業系統分別是windows和macintosh,microsoft是軟體行業的龍頭

。為了吸引更多客戶購買電腦,hp和apple請ms為他們開發兩款最常

用的軟體,辦公軟體和及時通訊工具。ms結了訂單後,分別為hp和

apple開發了office和msn。
上面的場景其實蘊含著我們常見的設計模式思維方式,code is

cheap,程式碼來了。
一:簡單工廠
Code
using System;
//ms的產品
public class Software
{
    private string softwareName;

    public virtual string SoftwareName
    {
        get { return softwareName; }
        set { softwareName = value; }
    }
    public string GetSoftwareName()
    {
        return softwareName;
    }
}
//ms的產品:office
public class Office:Software
{
    public override string GetSoftwareName()
    {
        this.SoftwareName = "Office";
        return “Office”;
    }
}
//ms的產品:msn
public class Msn : Software
{
    public override string GetSoftwareName()
    {
        this.SoftwareName = "Msn";
        return “Msn”;
    }
}

///


/// 簡單工廠
///

public class MsSoftwareFactory
{
    public static Software CreateSoftware(string

softwareName)
    {
        Software msSoftware = null;
        switch (softwareName)
        {
            default:
                break;
            case "office":
                msSoftware = new Office();
                break;
            case "msn":
                msSoftware = new Msn();
                break;
        }
        return msSoftware;
    }
}

 

///


/// 客戶端呼叫
///

public class Client {
    static void Main(string[] args)
    {
        Software msSoftware =

MsSoftwareFactory.CreateSoftware("office");
        Console.WriteLine(msSoftware.GetSoftwareName());
    }
}
上面的簡單工廠在一個方法體中有個switch...case,違背了“對擴

展開放,對修改封閉”的原則,即“開放-封閉原則”。下面的工廠

方法就克服了簡單工廠的缺點,降低了客戶端程式和產品物件的耦

合。

二:工廠方法
定義一個用於建立物件的介面,讓子類決定例項化哪一個類。工廠

方法使一個類的例項化延遲到其子類。

Code
using System;
//ms的產品
public class Software
{
    private string softwareName;

    public string SoftwareName
    {
        get { return softwareName; }
        set { softwareName = value; }
    }
    public virtual string GetSoftwareName()
    {
        return softwareName;
    }
}
//ms的產品:office
public class Office:Software
{
    public override string GetSoftwareName()
    {
        this.SoftwareName = "Office";
        return "Office";
    }
}
//ms的產品:msn
public class Msn : Software
{
    public override string GetSoftwareName()
    {
        this.SoftwareName = "Msn";
        return "Msn";
    }
}

interface ISoftwareFactory
{
    Software CreateSoftware();
}

///


/// office工廠
///

public class OfficeFactory:ISoftwareFactory
{
    public  Software CreateSoftware()
    {
        return new Office();
    }
}

///


/// msn工廠
///

public class MsnFactory : ISoftwareFactory
{
    public Software CreateSoftware()
    {
        return new Msn();
    }
}


///


/// 客戶端呼叫
///

public class Client {
    static void Main(string[] args)
    {
        ISoftwareFactory factory = new OfficeFactory();
        Software msSoftware = factory.CreateSoftware();
        Console.WriteLine(msSoftware.GetSoftwareName());
    }
}工廠方法的缺點是每加一個產品,就要建立一個對應的產品工廠類

,增加了額外的開發量。
三、抽象工廠
提供一個建立一系列相關或者相互依賴物件的介面,而無需指定它

們具體的類。
抽象工廠最經典的應用莫過於資料庫訪問程式。網上有很多這方面

的討論。不多說了。這裡我繼續用開篇講的場景來描述。
我們知道office和msn根據作業系統的不同可以分為windows版本的

和mac版本的,也許還有linux,unix版本的,歸根結底,這裡的產

品涉及到產品系列的問題,抽象工廠可以解決這個問題:
Code
using System;

//ms的產品:office
public class Office
{
    private string softwareName;

    public string SoftwareName
    {
        get { return softwareName; }
        set { softwareName = value; }
    }
}

public interface IOffice
{
    Office GetOffice();
}

//ms的windows版本Office
public class WinOffice : IOffice
{
    public Office GetOffice()
    {
        return new Office();
    }
}

//ms的macintosh版本Office
public class MacOffice : IOffice
{
    public Office GetOffice()
    {
        return new Office();
    }
}

//ms的產品:msn
public class Msn
{
    private string softwareName;

    public string SoftwareName
    {
        get { return softwareName; }
        set { softwareName = value; }
    }
}

public  interface IMsn
{
    Msn GetMsn();
}

//ms的windows版本msn
public class WinMsn:IMsn
{
    public Msn GetMsn()
    {
        return new Msn();
    }
}

//ms的macintosh版本msn
public class MacMsn : IMsn
{
    public Msn GetMsn()
    {
        return new Msn();
    }
}

interface ISoftwareFactory
{
    IOffice CreateOffice();
    IMsn CreateMsn();
}

///


/// windows版本的工廠
///

public class WindowsFactory:ISoftwareFactory
{
    public IOffice CreateOffice()
    {
        return new WinOffice();
    }
    public IMsn CreateMsn()
    {
        return new WinMsn();
    }
}

///


/// macintosh版本的工廠
///

public class MacFactory : ISoftwareFactory
{
    public IOffice CreateOffice()
    {
        return new MacOffice();
    }
    public IMsn CreateMsn()
    {
        return new MacMsn();
    }
}


///


/// 客戶端呼叫
///

public class Client {
    static void Main(string[] args)
    {
        ISoftwareFactory factory = new WindowsFactory();
        IOffice ffice = factory.CreateOffice();
        IMsn msn = factory.CreateMsn();
    }
}

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-567489/,如需轉載,請註明出處,否則將追究法律責任。

相關文章