設計模式——簡單工廠 SimpleFactory

場景:解除上端對細節的依賴,把細節包一層,在另一層中處理

抽象類

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignMode.Interface
{
    public abstract class BasePhone
    {
        public abstract void Call();
        public abstract void Text();
    }
}

蘋果手機

using DesignMode.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SimpleFactory
{
    public class iPhone : BasePhone
    {
        public override void Call()
        {
            Console.WriteLine("use {0} call", this.GetType().Name);
        }

        public override void Text()
        {
            Console.WriteLine("use {0} text", this.GetType().Name);
        }
    }
}

華爲手機

using DesignMode.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SimpleFactory
{
    public class Honor : BasePhone
    {
        public override void Call()
        {
            Console.WriteLine("use {0} call", this.GetType().Name);
        }

        public override void Text()
        {
            Console.WriteLine("use {0} text", this.GetType().Name);
        }
    }
}

三星手機

using DesignMode.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SimpleFactory
{
    public class Galaxy : BasePhone
    {
        public override void Call()
        {
            Console.WriteLine("use {0} call", this.GetType().Name);
        }

        public override void Text()
        {
            Console.WriteLine("use {0} text", this.GetType().Name);
        }
    }
}

工廠類

using Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Model
{
    /// <summary>
    /// 解除上端對細節的依賴,把細節放到工廠中去
    /// </summary>
    public class ObjectFactory
    {
        /// <summary>
        /// 創建對象
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static BasePhone CreateBasePhone(PhoneType type)
        {
            switch (type)
            {
                case PhoneType.Galaxy:
                    return new Galaxy();
                case PhoneType.iPhone:
                    return new iPhone();
                case PhoneType.Honor:
                    return new Honor();
                default:
                    throw new Exception("wrong PhoneType");
            }
        }

        /// <summary>
        /// 枚舉
        /// </summary>
        public enum PhoneType
        {
            Galaxy,
            iPhone,
            Honor
        }
    }
}

上端調用

using Interface;
using Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            BasePhone galaxy = ObjectFactory.CreateBasePhone(ObjectFactory.PhoneType.Galaxy);
            BasePhone iphone = ObjectFactory.CreateBasePhone(ObjectFactory.PhoneType.iPhone);
            Console.ReadKey();
        }
    }
}

這裏寫圖片描述

到這 實現簡單工廠基礎版


上面的上端調用 可能看起來還是有點不爽,因爲貌似還有點細節

BasePhone galaxy = ObjectFactory.CreateBasePhone(ObjectFactory.PhoneType.Galaxy);

ObjectFactory.PhoneType.Galaxy

我就是不想讓上端寫明傳什麼枚舉類型

接着改造 我的工廠類 這回我用了配置文件

using Interface;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Model
{
    /// <summary>
    /// 解除上端對象細節的依賴,把細節放到工廠中去
    /// </summary>
    public class ObjectFactory2
    {
        /// <summary>
        /// 枚舉
        /// </summary>
        public enum PhoneType
        {
            Galaxy,
            iPhone,
            Honor
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static BasePhone CreateBasePhoneConfig()
        {
            //把字符串轉換成枚舉類型
            PhoneType type = (PhoneType)Enum.Parse(typeof(PhoneType), ConfigurationManager.AppSettings["PhoneType"]);
            switch (type)
            {
                case PhoneType.Galaxy:
                    return new Galaxy();
                case PhoneType.iPhone:
                    return new iPhone();
                default:
                    throw new Exception("wrong PhoneType");
            }
        }
    }
}

配置文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>

  <appSettings>
    <!--<add key="PhoneType" value="iPhone"/>-->
    <add key="PhoneType" value="Galaxy"/>
  </appSettings>
</configuration>

上端調用

using Interface;
using Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            BasePhone galaxy = ObjectFactory2.CreateBasePhoneConfig();
            Console.ReadKey();
        }
    }
}

這裏寫圖片描述


既然可以讀取配置文件來搞,那麼幹脆用反射玩

改造下簡單工廠類

using Interface;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Model
{
    /// <summary>
    /// 解除上端對象細節的依賴,把細節放到工廠中去
    /// </summary>
    public class ObjectFactory3
    {
        public static BasePhone CreateBasePhoneConfigReflection()
        {
            //通過配置文件獲取程 序集名稱 [命名空間]
            string dllName = ConfigurationManager.AppSettings["dllName"];
            //通過配置文件獲取類 型全名稱 [命名空間+類名]
            string className = ConfigurationManager.AppSettings["className"];
            //反射創建對象
            return (BasePhone)Activator.CreateInstance(dllName,className).Unwrap();
        }
    }
}

配置文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>

  <appSettings>
    <!--程序集名稱 [命名空間]-->
    <add key="dllName" value="Model"/>
    <!--類型全名稱 [命名空間+類名]-->
    <add key="className" value="Model.Galaxy"/>
  </appSettings>
</configuration>

上端調用

using Interface;
using Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            BasePhone galaxy = ObjectFactory3.CreateBasePhoneConfigReflection();
            Console.ReadKey();
        }
    }
}

這裏寫圖片描述

最後交代一下,用反射的方式玩工廠是最靈活的,從代碼上來說 枚舉都可以去掉了 !
比方說要加個“小米”手機,那麼我們搞個“小米”類,繼承一下”手機父類”, 編譯一下,就可以跑起來,當然配置文件要改動

從程序設計原則上講,簡單工廠是違背了 “單一職責”
程序設計沒有銀彈

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章