设计模式之-简单工厂模式

Posted hhzblogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之-简单工厂模式相关的知识,希望对你有一定的参考价值。

简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
 
就以之前玩过的一个游戏为例子,通过简单工厂来实现一系列功能。
首先这个游戏分为5个门派(金,木,水,火,土),每个不同的门派拥有不同的技能。
 
首先定义一个门派接口,然后分别定义几个实现门派。
    /// <summary>
    /// 门派接口
    /// </summary>
    public interface ISects
    {
        /// <summary>
        /// 技能
        /// </summary>
        void Skill();
    }
    /// <summary>
    /// 金系门派
    /// </summary>
    public class Gold : ISects
    {
        public void Skill()
        {
            Console.WriteLine("金系门派技能:金光乍现");
        }
    }
    /// <summary>
    /// 木系门派
    /// </summary>
    public class Wood : ISects
    {
        public void Skill()
        {
            Console.WriteLine("木系门派技能:摘叶飞花");
        }
    }
    /// <summary>
    /// 水系门派
    /// </summary>
    public class Water : ISects
    {
        public void Skill()
        {
            Console.WriteLine("水系门派技能:滴水穿石");
        }
    }

接下来是调用:

    ISects gold = new Gold();
    gold.Skill();

    ISects wood = new Wood();
    wood.Skill();

    ISects water = new Water();
    water.Skill()

我们来看一下结果:

技术分享图片

没有意外的得到了我们想要的结果,但是对于我们上端(调用端)而言,我们高度耦合了细节,也就违背了我们开发时经常挂在嘴边的"低耦合",那么现在我们遇到了这种问题,现在当然要来解决了。

1.用简单工厂来解决我们遇到的问题

而"简单工厂"就能很好的解决这类问题。

我们只需要将创建对象这个动作转移到另一个地方即可。

建立一个工厂类,专门为我们生产我们需要的对象。

    public class Factory
    {
        public static ISects CreateInstance(SectsType sectsType)
        {
            switch (sectsType)
            {
                case SectsType.Gold:
                    return new Gold();
                case SectsType.Wood:
                    return new Wood();
                case SectsType.Water:
                    return new Water();
                case SectsType.Fire:
                    throw new ArgumentException("没有Fire门派");
                case SectsType.Soil:
                    throw new ArgumentException("没有Soil门派");
                default:
                    throw new ArgumentException();
            }
        }

        public enum SectsType
        {
            Gold,
            Wood,
            Water,
            Fire,
            Soil
        }
    }

然后调用方式如下:

    ISects gold = Factory.CreateInstance(Factory.SectsType.Gold);
    gold.Skill();

    ISects wood = Factory.CreateInstance(Factory.SectsType.Wood);
    gold.Skill();

结果如下:

 技术分享图片

上面所示就是用简单工厂很好的解决了我们的问题。

2.简单工厂+配置文件 使得我们的项目变的可配置

配置文件如下:

  <appSettings>
    <add key="SectsTypeName" value="Water"/>
  </appSettings>

工厂内部创建对象的方法如下:

    private static string SectsTypeName = ConfigurationManager.AppSettings["SectsTypeName"];
    public static ISects CreateInstanceWithConfig()
    {
        switch (Enum.Parse(typeof(SectsType), SectsTypeName))
        {
            case SectsType.Gold:
                return new Gold();
            case SectsType.Wood:
                return new Wood();
            case SectsType.Water:
                return new Water();
            case SectsType.Fire:
                throw new ArgumentException("没有Fire门派");
            case SectsType.Soil:
                throw new ArgumentException("没有Soil门派");
            default:
                throw new ArgumentException();
        }
    }

结果如下:

技术分享图片

3.简单工厂+配置文件+反射 使得我们的项目变得可扩展

配置文件如下:

  <appSettings>
    <add key="SectsTypeNameWithReflect" value="SimpleFactory,SimpleFactory.Wood"/>
  </appSettings>

工厂类创建对象方法代码如下:

        private static string SectsTypeNameWithReflect = ConfigurationManager.AppSettings["SectsTypeNameWithReflect"];
        public static ISects CreateInstanceWithReflect()
        {
            string assemblyName = SectsTypeNameWithReflect.Split(,)[0];
            string typeName = SectsTypeNameWithReflect.Split(,)[1];
            return (ISects)Activator.CreateInstance(assemblyName,typeName).Unwrap();
        }

调用代码:

    ISects wood = Factory.CreateInstanceWithReflect();
    wood.Skill();

结果如下:

技术分享图片

简单工厂到这里,可所谓是已经非常强大了,当我们需要添加一个新的门派的时候,只需要要添加新的门派类即可,当有一个第三方类库也实现了我们的门派接口时,我们只需要将它的dll拷贝过来就行,然后就可以使用了,这才是真正做到了可扩展。

 源代码地址:https://github.com/houzhenhuang/DesignPattern

 

以上是关于设计模式之-简单工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之简单工厂模式

设计模式之简单工厂模式

创建型模式之简单工厂模式实例及代码操作

java设计模式之简单工厂模式

设计模式之工厂模式

设计模式之工厂模式-简单工厂(02)