Simple Factory

摘要:Simple Factory

只是單純做做筆記,如果有任何不對的地方請跟我說喔。

Simple Factory(簡單模式)在Design Patterns裡算是最好理解的,大概的意思就是實體化的動作交給Factory Class來處理,好處就是程式可以在執行時動態決定要實體化哪個類別。

假設有一個食品工廠裡面有生產不同食品的生產線,例如裡面有生產飲料或餅乾等等.....或其他更多的產品。

產品類別:

namespace prjSimpleFactory
{
    class Product
    {
        public virtual void Produce()
        {

        }
    }
}

飲料類別:

namespace prjSimpleFactory
{
    class Drink:Product 
    {
        public override void Produce()
        {
            Console.WriteLine("我是飲料生產線");
        }
    }
}

餅乾類別:

namespace prjSimpleFactory
{
    class Cookie:Product
    {
        public override void Produce()
        {
            Console.WriteLine("我是餅乾生產線");
        }
    }
}

工廠類別:
裡面的邏輯判斷用以決定在什麼時候建構哪一類型的實體化產品,就好像我跟工廠要某些東西,工廠只要生產好東西然後把東西交給我,我不必管工廠是怎麼把東西做出來的。

namespace prjSimpleFactory
{
    class ProductFactory
    {
        public static Product createProduct(string product)
        {
            Product objProduct = null;

            switch(product)
            {
                case "drink":
                    objProduct = new Drink();
                    break;
                case "cookie":
                    objProduct = new Cookie();
                    break;
                default:  
                    throw new Exception();
            }

            return objProduct;
        }
    }
}

Client:如果要飲料,createProduct()只要傳入drink就可以了,要餅乾就傳入cookie。

private void Form1_Load(object sender, EventArgs e)
        {
            //動態決定要實體化的類別
             string strProductName = "drink";

            Product prod = ProductFactory.createProduct(strProductName);

            prod.Produce();     
           
        }

假設今天食品工廠要多生產一個牛奶的生產線,那程式就要多新增一個Milk的子類別,而且產品工廠的switch那邊也要增加邏輯判斷,這樣就不符合OO的 Open-Closed Principle(開放-封閉原則)精神。解決方法就是利用C#的ㄧ個機制,叫做Reflection(反射)的機制,這樣就不用針對不同的狀況寫不同邏輯的判斷。

改良後的工廠類別:

using System.Reflection;

namespace prjSimpleFactory
{
    class ProductFactory
    {
        private static readonly string AssemblyName = "prjSimpleFactory";

        public static Product createProduct(string product)
        {
            string className = AssemblyName + "." + product;

            return (Product)Assembly.Load(AssemblyName).CreateInstance(className);
       
        }
    }
}