1. 程式人生 > >用心理解設計模式——工廠方法模式 (Factory Method Pattern)

用心理解設計模式——工廠方法模式 (Factory Method Pattern)

前置文章: 用心理解設計模式——設計模式的原則 

設計模式相關程式碼已統一放至 我的 Github

 

一、定義

  建立型模式之一。

  Define an interface for creating an object, but let subclass decide which class to instantiate .

  Factory Method lets a class defer instantiation to subclass.

 (定義一個用於建立物件的介面,讓子類決定例項化哪一個類。工廠方法使一個類的例項化延遲到其子類)

二、結構解析

  工廠方法模式的一般結構有四種角色:抽象工廠、具體工廠、抽象產品、具體產品。

  它將 簡單工廠模式(靜態工廠方法模式)  中的工廠類抽象為一個介面(抽象工廠)(這個介面中定義了一個用於建立物件的方法,即工廠方法) 。然後派生出具體工廠類與具體產品類一一對應 ,即, 決定了工廠就意味著決定了產品,最後在具體工廠類中例項化具體產品類。從而使一個類(具體產品類)的例項化延遲到其子類(從抽象工廠類延遲到具體工廠類)。 

三、評價

  工廠方法模式解決了 簡單工廠模式 (非泛型的實現)違背開閉原則、單一職責原則的問題。

  當有產品新增時,不用再需要修改工廠類(抽象工廠類和具體工廠類都不需要修改),而是新增一個與之對應的具體工廠類。

四、實現

//獨立負責一個產品的工廠方法
namespace FactoryMethod
{
    //抽象產品類
    public abstract class Product { }

    public class ConcreteProduct1 : Product { }

    public class ConcreteProduct2 : Product { }
    //可擴充套件新的具體產品
    //...

    //抽象工廠類
    public abstract class Creator
    {
        //定義建立物件的公共介面
        public abstract Product FactorMethod();
    }

    //具體工廠類1, 只用來生產產品1
    public class ConcreteCreator1 : Creator
    {
        public override Product FactorMethod()
        {
            return new ConcreteProduct1();
        }
    }

    //具體工廠類2,只用來生產產品2
    public class ConcreteCreator2 : Creator
    {
        public override Product FactorMethod()
        {
            return new ConcreteProduct2();
        }
    }

    public class Client
    {
        private void Main()
        {
            ConcreteCreator1 factory1 = new ConcreteCreator1();
            ConcreteCreator2 factory2 = new ConcreteCreator2();

            factory1.FactorMethod();
            factory2.FactorMethod();
        }
    }
}

 缺點:工廠方法模式中,具體工廠類直接依賴具體產品類。違背依賴倒置原則(高層模組不應該依賴低層模組,它倆都應該依賴低層模組的抽象) 。

五、泛型工廠方法模式

  可以認為泛型T和Object型別一樣,是所有型別的抽象基類。

  這樣,具體工廠類(高層模組)將只依賴泛型T(低層模組的抽象基類),並且當產品新增時,也不需要任何改動。

  具體實現如下:

  抽象工廠類中定義一個用於建立產品物件的公共泛型介面,泛型T 約束為抽象產品類。

  實際工廠類繼承抽象工廠類,並實現這個泛型介面,通過反射對T進行例項化。

using System;

//泛型工廠方法
namespace FactoryMethod.GenericFunction
{
    //抽象產品類
    public abstract class Product { }

    //具體產品類
    public class ConcreteProduct1 : Product { }
    public class ConcreteProduct2 : Product { }
    //可擴充套件新的具體產品
    //...

    //抽象工廠類
    public abstract class Creator
    {
        //定義建立物件的公共介面
        public abstract T FactorMethod<T>() where T : Product;
    }

    //具體工廠類
    public class ConcreteCreator : Creator
    {
        //實現建立物件的公共介面
        public override T FactorMethod<T>()
        {
            return Activator.CreateInstance<T>();
        }
    }

    public class Client
    {
        private void Main()
        {
            //建造工廠
            ConcreteCreator factory = new ConcreteCreator();
            //建立具體產品1
            factory.FactorMethod<ConcreteProduct1>();
            //建立具體產品2
            factory.FactorMethod<ConcreteProduct2>();
        }
    }
}