2014年8月5日 星期二

抽象工廠模式(Abstract Factory)

  • 抽象工廠特性:
    • 意義在於在工廠內,把產品抽象出來,交由實體工廠生產,產品可以由不同元件(object)所合成,客製化生產不同類別的產品,讓各個實體工廠可以去實作實際的生產細節
    • 應用的OO精神 :多用合成(Composition),少用繼承(Inheritance)
    • 這邊合成的意思是於Client端只會應用interface(例如:AbstractFactory)來生產各種產品,而不需要明白指定是哪種實體的產品(concrete product),也不需要知道AbstractFactory會怎麼合成產品的細節,AbstractFactory會封裝工廠的產品生產過程,Client 端只需要會使用抽象工廠即可,不需要去明白工廠製作細節
    • 網路上各種例子表示抽像工廠和工廠方法的界定十分模糊,這裡的Abstract Factory的"Abstract"只是一個觀念,並非一定要用Java 或C#語言中的Abstract Class 修飾詞(modifier),有時候可以用Interface來實作,有時候會使用Abstract,因此符合上述概念,抽象工廠模式有相當大的實作彈性
  • 看一下抽像工廠的類別圖(Class diagram):
      • AbstractFactory - 宣告一個可以生產AbstractProduct 的interface
      • ConcreteFactory - 實作AbstractFactory, 並且生產ConcreteFactory
      • AbstractProduct - 宣告一個Product的interface
      • Product - 實作AbstractProduct, 定義一個實際的產品, 包含產品特性
      • Client - 只直接和AbstractFactory和AdstractProduct互動
  • 以下的類別圖引用自:"Abstract factory UML" by Giacomo Ritucci - My own work, generated with omondo for eclipse 3.1.2, modified with inkscape.. Licensed under Creative Commons Attribution-Share Alike 3.0 via Wikimedia Commons - http://commons.wikimedia.org/wiki/File:Abstract_factory_UML.svg#mediaviewer/File:Abstract_factory_UML.svg

  • 接下來就是使用抽象工廠的程式碼例子,以下例子使用電子產品抽象工廠生產不同的電子產品:個人電腦、手機、平版。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AbstractFactory
{
    class Program
    {
        static void Main(string[] args)
        {
            Client client = new Client();

            client.ProductList.Add
                (client.MakeAnOrder(ProductMeum.SmartPhone));
            client.ProductList.Add
                (client.MakeAnOrder(ProductMeum.PersonalComputer));
            client.ProductList.Add
                (client.MakeAnOrder(ProductMeum.Tablelet));

            client.DemoProductList();
        }
    }

    internal class Client
    {
        private ElectricApplianceFactory factory;

        private List productList
            = new List();

        public List ProductList 
        { 
            get
            {
                return productList;
            }
            set
            {
                productList = value;
            }
        }

        public ElectricApplianceProduct MakeAnOrder(ProductMeum meum)
        {
            switch (meum)
            {
                    case ProductMeum.Tablelet:
                    factory = new TableletFactory();
                    break;

                    case ProductMeum.SmartPhone:
                    factory = new SmartPhoneFactory();
                    break;

                    case ProductMeum.PersonalComputer:
                    factory = new PersonalComputerFactory();
                    break;
            }

            return factory.CreateProduct();
        }

        public void DemoProductList()
        {
            foreach (var electricApplianceProduct in ProductList)
            {
                electricApplianceProduct.Compute();
            }

            Console.ReadKey();
        }
    }

    interface ElectricApplianceProduct
    {
        void Compute();
    }

    internal class PersonalComputer : ElectricApplianceProduct
    {
        public void Compute()
        {
            Console.WriteLine("PC computing...");
        }
    }

    internal class SmartPhone : ElectricApplianceProduct
    {
        public void Compute()
        {
            Console.WriteLine("SmartPhone computing...");
        }
    }

    internal class Tablelet : ElectricApplianceProduct
    {
        public void Compute()
        {
            Console.WriteLine("Tablelet computing...");
        }
    }

    internal class PersonalComputerFactory : ElectricApplianceFactory
    {
        private PersonalComputer pc;

        public ElectricApplianceProduct CreateProduct()
        {
            pc = new PersonalComputer();
            return pc;
        }
    }

    internal class SmartPhoneFactory : ElectricApplianceFactory
    {
        private SmartPhone smartPhone;

        public ElectricApplianceProduct CreateProduct()
        {
            smartPhone = new SmartPhone();
            return smartPhone;
        }
    }

    internal class TableletFactory : ElectricApplianceFactory
    {
        private Tablelet tablelet;

        public ElectricApplianceProduct CreateProduct()
        {
            tablelet = new Tablelet();
            return tablelet;
        }
    }

    interface ElectricApplianceFactory
    {
        ElectricApplianceProduct CreateProduct();
    }
}

enum ProductMeum
{
    Tablelet,
    SmartPhone,
    PersonalComputer
}

沒有留言:

張貼留言