Factory Pattern (泡麵篇)

Factory Pattern (泡麵篇)

使用工具: StarUML, VS2008

以前還蠻喜歡無聊時OO一下, 前兩天看到7-11的泡麵除了統一的牌子外, 竟然還有統一超商的牌子, 而且都是由統一台南工廠出品? 想不到除了開設據點喜歡自我競爭外, 連產品也是, 可憐的加盟主只是該公司的犠牲品, 犠牲健康、時間, 只為了成就24小時高品質的服務和國家稅收... 又離題了~ (詳細內容請見血汗超商) .

在剛開始學工廠模板裡,是由Main去使用工廠,工廠負責生產產品,但我一直卡在Factory(工廠),因為小弟我從小就一直在工廠工作,所以總覺得一間工廠只做一項產品,實在很不可思議,所以我自己把它改變成:工廠去使用製程,而製程負責產生產品。比較符合我的大腦邏輯.

示意圖 (初步的概念)

 

第一步: 設計抽象的類別

1. 速食麵工廠: (Main)

    負責開工.

2. 速食麵製程: (Factory)

    2.1 只能單一入口依製程代程取得製程.

    2.2 製造N個速食麵.

3. 速食麵: (Production)

    2.1 有麵條,醬包,製造日期及保存期.

    2.2 可用熱水來沖泡.

    2.3 或用鍋子煮.

abstract

        public void 開工() {
            速食麵製程 obj速食麵製程 = 速食麵製程.取得製程("FactoryPtn.袋裝.有料速食麵製程");
            obj速食麵製程.製造泡麵(3);
        }
    }

----------------

        public static 速食麵製程 取得製程(string name) {
            Assembly obj製程組件 = Assembly.GetExecutingAssembly();
            速食麵製程 obj速食麵製程 = obj製程組件.CreateInstance(name) as 速食麵製程;
            return obj速食麵製程;
        }
        abstract public void 製造泡麵(int 數量);
    }

----------------

        public DateTime 製造日期;
        public DateTime 保存期限;
        public object 麵條;
        public object 醬包;

        abstract public void 沖泡(object 熱水);
        abstract public void 鍋煮(object 水, object 鍋子);
    }

第二步: 實作

4. 有料速食麵製程: (Factory)

    實作製造泡麵

5. 有料速食麵

    5.1 除擁有父類別之屬性外, 另外多了肉醬包

    5.2 實作沖泡及鍋煮操作方法

factory

        public override void 製造泡麵(int 數量) {
            for (int i = 0; i < 數量; i++) {
                System.Console.WriteLine("開始製造" + typeof(有料速食麵).ToString());
                有料速食麵 obj有料速食麵 = new 有料速食麵()
                {
                    醬包 = "醬包",
                    麵條 = "麵條",
                    肉醬包 = "肉醬包",
                    製造日期 = DateTime.Today,
                    保存期限 = DateTime.Today.AddMonths(6)
                };
                System.Console.WriteLine("做好一份" + obj有料速食麵.ToString());
                倉庫.入倉(obj有料速食麵);
                System.Console.WriteLine("一份" + obj有料速食麵.ToString() + "入倉");
            }
        }
    }

---------------

        public object 肉醬包;
        public override void 沖泡(object 熱水) {
            System.Console.WriteLine("把碗準備好");
            System.Console.WriteLine("在碗內放入" + this.醬包.ToString());
            System.Console.WriteLine("在碗內放入適量" + 熱水.ToString());
            System.Console.WriteLine("把碗蓋起來");
            System.Console.WriteLine("等待3分鐘 ... ");
            System.Console.WriteLine("在碗內放入" + this.肉醬包.ToString());
            System.Console.WriteLine("可以吃了!! ");
        }

        public override void 鍋煮(object 水, object 鍋子) {
            System.Console.WriteLine("把" + 鍋子.ToString() + "放在瓦斯爐上");
            System.Console.WriteLine("在" + 鍋子.ToString() + "上放入適量" + 水.ToString());
            System.Console.WriteLine("在" + 鍋子.ToString() + "放入" + this.麵條.ToString());
            System.Console.WriteLine("開啟瓦斯爐");
            System.Console.WriteLine("等待3分鐘 ... ");
            System.Console.WriteLine("關閉瓦斯爐");
            System.Console.WriteLine("在" + 鍋子.ToString() + "放入" + this.醬包.ToString());
            System.Console.WriteLine("在" + 鍋子.ToString() + "放入" + this.肉醬包.ToString());            
            System.Console.WriteLine("可以吃了!! ");
        }
    }

    result (結果頁)


我之前第一次做完Factory Pattern時, 覺得這種1對1的程式碼到底幹嘛要弄得這麼麻煩, 用建構子就好何必要多一個Factory類別呢?
其實不然, 因為sample比較簡單有時會失去其原意, 想想如果把有料速食麵製程改成袋裝速食麵製程, 此時Factory不就可以生產性質相近但多種不同的速食麵.
延生性的想法: 雖然在sample中我沒有使用到介面, 但實務上我通常會制立出interface, 讓程式碼都是在使用interface, 可以讓你在遠端呼叫或本機引用時, 得到很好的彈性去變化.
 
至於為什麼我會很常用這個模板呢? 因為我都假設需求不完整, 設計不確實, 透過工廠模板, 讓Code不會綁死在一起, 修改或重構起來也不會太累.

下載: 完整程式碼