返回

8.工厂方法模式

定义一个可以产生对象的接口,但是让子类决定要产生哪一个类的对象。工厂方法模式让类的实例化程序延迟到子类中实施。

工厂方法模式

定义一个可以产生对象的接口,但是让子类决定要产生哪一个类的对象。工厂方法模式让类的实例化程序延迟到子类中实施。

工厂方法模式的定义

工厂方法模式就是将类“产生对象的流程”集合管理的模式。集合管理带来的好处是:

  1. 能针对对象产生的流程定指规则
  2. 减少客户端参与对象生成的过程,尤其是对于那种对象生产过程过于复杂的,如果让客户端操作对象的组装过程,将使得客户端与该类的耦合度(即依赖度)过高,不利于后续的项目维护

参与者的说明如下:

  • Product(产品类)
    • 定义产品类的操作接口,而这个产品将由工厂产出
  • ConcreteProduct(产品实现)
    • 实现产品功能的类,可以不只定义一个产品实现类,这些产品实现类的对象都会由ConcreteCreator(工厂实现类)产生。
  • Creator(工厂类)
    • 定义能产生Product(产品类)的方法:FactoryMethod
  • ConcreteCreator(工厂实现类)
    • 实现FactoryMethod,并产生指定的ConcreteProduct(产品实现)。

具体实现

方法一:由子类实现

定义一个可以产生对象的接口,让子类决定要产生哪一个类的对象

    public abstract class Product
    {
    }

    //产品对象A
    public class ConcreteProductA : Product
    {
        public ConcreteProductA()
        {
            Debug.Log("生成对象A");
        }
    }

    //产品对象B
    public class ConcreteProductB : Product
    {
        public ConcreteProductB()
        {
            Debug.Log("生成对象B");
        }
    }

    public abstract class Creator
    {
        //子类返回对应的Product类型对象
        public abstract Product FactoryMethod();
    }

    //生产ProductA的工厂
    public class ConcreteCreatorProductA : Creator
    {
        public override Product FactoryMethod()
        {
            return new ConcreteProductA();
        }

        public ConcreteCreatorProductA()
        {
            Debug.Log("生产工厂:ConcreteCreatorProductA");
        }
    }

    //生产ProductB的工厂
    public class ConcreteCreatorProductB : Creator
    {
        public override Product FactoryMethod()
        {
            return new ConcreteProductB();
        }

        public ConcreteCreatorProductB()
        {
            Debug.Log("生产工厂:ConcreteCreatorProductB");
        }
    }

方法二:在FactoryMethod中增加参数

    public abstract class Product
    {
    }

    //产品对象A
    public class ConcreteProductA : Product
    {
        public ConcreteProductA()
        {
            Debug.Log("生成对象A");
        }
    }

    //产品对象B
    public class ConcreteProductB : Product
    {
        public ConcreteProductB()
        {
            Debug.Log("生成对象B");
        }
    }

    //重新实现factory mathod,以返回Product类型对象
    public class ConcreteCreator_MethodType : Creator_MethodType
    {
        public ConcreteCreator_MethodType()
        {
            Debug.Log("生产工厂:ConcreteCreator_MethodType");
        }

        public override Product FactoryMethod(int Type)
        {
            switch (@Type)
            {
                case 1:
                    return new ConcreteProductA();
                case 2:
                    return new ConcreteProductB();
                default:
                    Debug.Log("Type[" + Type + "]无法产生对象");
                    break;
            }

            return null;
        }
    }

方法三:Creator泛型类

    public abstract class Product
    {
    }

    //产品对象A
    public class ConcreteProductA : Product
    {
        public ConcreteProductA()
        {
            Debug.Log("生成对象A");
        }
    }

    //产品对象B
    public class ConcreteProductB : Product
    {
        public ConcreteProductB()
        {
            Debug.Log("生成对象B");
        }
    }
    public class Creator_GenericClass<T> where T : Product, new()
    {
        public Creator_GenericClass()
        {
            Debug.Log("生产工厂Creator_GenericClass<" + typeof(T).ToString() + ">");
        }

        public Product FactoryMethod()
        {
            return new T();
        }
    }

    public class Test
    {
        void UnitTest()
        {
            //使用Generic Class
            //负责ProduceA的工厂
            Creator_GenericClass<ConcreteProductA> Creator_ProductA = new Creator_GenericClass<ConcreteProductA>();
            //负责ProduceB的工厂
            Creator_GenericClass<ConcreteProductB> Creator_ProductB = new Creator_GenericClass<ConcreteProductB>();
        }
    }

方法四:FactoryMethod泛型方法


    public abstract class Product
    {
    }

    //产品对象A
    public class ConcreteProductA : Product
    {
        public ConcreteProductA()
        {
            Debug.Log("生成对象A");
        }
    }

    //产品对象B
    public class ConcreteProductB : Product
    {
        public ConcreteProductB()
        {
            Debug.Log("生成对象B");
        }
    }

    interface Creator_GenericMethod
    {
        Product FactoryMethod<T>() where T : Product, new();
    }

    public class ConcreteCreator_GenericMethod : Creator_GenericMethod
    {
        public ConcreteCreator_GenericMethod()
        {
            Debug.Log(("生产工厂:ConcreteCreator_GenericMethod"));
        }

        public Product FactoryMethod<T>() where T : Product, new()
        {
            return new T();
        }
    }

    public class Test2
    {
        void UnitTest()
        {
            ConcreteCreator_GenericMethod theCreatorGM = new ConcreteCreator_GenericMethod();
            Product theProductA = theCreatorGM.FactoryMethod<ConcreteProductA>();
            Product theProductB = theCreatorGM.FactoryMethod<ConcreteProductB>();
        }
    }

使用工厂方法模式产生角色对象

参与者的说明如下:

  • ICharacterFactory:负责产生角色类Icharacter的工厂接口,并提供两个工厂方法来产生不同阵营的角色对象:CharacterSoldier负责产生玩家阵营的角色对象;CharacterEnemy负责产生敌方阵营的角色对象。
  • CharacterFactory:继承并实现ICharacter工厂接口的类,其中实现的工厂方法是实际产生对象的敌方。
  • ISoldier、SoldierCapion:由工厂类产生的“产品”
  • IEnemy、EnemyElf:由工厂类产生的另一项“产品”

工厂方法模式的优点

角色工厂类,将“角色类群组”产生的对象的实现,都整合到两个工厂方法(FactoryMethod)下,并将有关的程序从客户端删除,同时降低了客户端与“角色生产过程”的耦合度。此外,角色生产后的后续设置功能,也都在同意敌方是下面,让开发人员能快速了解类之间的关联性及设置的先后顺序。

与其他模式的合作

  • 角色工厂中,产生不同阵营的角色时,会搭配建造者模式的需求,将需求的参数设置给各角色的建造者。
  • 本地资源加载工厂若同时要求系统性能的优化,可使用代理者模式来优化加载性能。
  • 属性产生工厂可使用享元模式来减少重复对象的产生。