代码改变世界

利用反射实现工厂模式

2016-01-26 23:05  佳佳的博客  阅读(551)  评论(0编辑  收藏  举报

需求:工厂类根据参数生成对应类的实例。

示例:

RoomParts.cs

namespace ReflectionFactory
{
    /// <summary>
    /// 屋子产品的零件
    /// </summary>
    public enum RoomParts
    {
        Roof,
        Window,
        Pillar
    }
}

ProductAttribute.cs

using System;

namespace ReflectionFactory
{
    /// <summary>
    /// 这个特性用来附加在产品类型之上,
    /// 来标注该类型代表哪个产品,方便反射使用
    /// </summary>
    public class ProductAttribute : Attribute
    {
        /// <summary>
        /// 标注零件的成员
        /// </summary>
        private RoomParts _myRoomPart;
        public ProductAttribute(RoomParts part)
        {
            _myRoomPart = part;
        }
        public RoomParts RoomPart
        {
            get
            {
                return _myRoomPart;
            }
        }
    }
}

ProductListAttribute.cs

using System;

namespace ReflectionFactory
{
    /// <summary>
    /// 这个特性用来附加在产品接口之上
    /// 用来标注一共实现了多少产品零件,方便反射使用
    /// </summary>
    public class ProductListAttribute : Attribute
    {
        /// <summary>
        /// 产品类型集合
        /// </summary>
        private Type[] _myList;
        public ProductListAttribute(Type[] products)
        {
            _myList = products;
        }
        public Type[] ProductList
        {
            get
            {
                return _myList;
            }
        }
    }
}

IProduct.cs

using System;

namespace ReflectionFactory
{
    /// <summary>
    /// 产品零件接口,
    /// 需要添加所有实现该接口的列表
    /// </summary>
    [ProductList(new Type[] { typeof(Roof), typeof(Window), typeof(Pillar) })]
    public interface IProduct
    {
        string GetName();
    }
}

Roof.cs

namespace ReflectionFactory
{
    /// <summary>
    /// 屋顶类型
    /// </summary>
    [Product(RoomParts.Roof)]
    public class Roof : IProduct
    {
        public string GetName()
        {
            return "屋顶";
        }
    }
}

Window.cs

namespace ReflectionFactory
{
    /// <summary>
    /// 窗户类型
    /// </summary>
    [Product(RoomParts.Window)]
    public class Window : IProduct
    {
        public string GetName()
        {
            return "窗户";
        }
    }
}

Pillar.cs

namespace ReflectionFactory
{
    /// <summary>
    /// 柱子类型
    /// </summary>
    [Product(RoomParts.Pillar)]
    public class Pillar : IProduct
    {
        public string GetName()
        {
            return "柱子";
        }
    }
}

IFactory.cs

namespace ReflectionFactory
{
    public interface IFactory
    {
        IProduct Produce(RoomParts part);
    }
}

Factory.cs

using System;
using System.Reflection;

namespace ReflectionFactory
{
    /// <summary>
    /// 工厂类型
    /// </summary>
    public class Factory : IFactory
    {
        public IProduct Produce(RoomParts part)
        {
            // 通过反射,从IProduct接口获得属性
            // 从而获得所有的产品零件列表
            ProductListAttribute attr = Attribute.GetCustomAttribute(typeof(IProduct), 
                typeof(ProductListAttribute)) as ProductListAttribute;

            // 遍历所有的实现产品零件类型
            foreach (Type type in attr.ProductList)
            {
                // 利用发射查找其属性
                ProductAttribute pa = Attribute.GetCustomAttribute(type, 
                    typeof(ProductAttribute)) as ProductAttribute;
                // 确定是否是需要的零件
                if (pa.RoomPart == part)
                {
                    // 利用反射创建产品零件类型
                    Object product = Assembly.GetExecutingAssembly().CreateInstance(type.FullName);
                    return product as IProduct;
                }
            }
            
            return null;
        }
    }
}

FactoryManager.cs

using System;

namespace ReflectionFactory
{
    /// <summary>
    /// 工厂管理类型
    /// </summary>
    public class FactoryManager
    {
        public static IProduct GetProduct(RoomParts part)
        {
            // 一共只有一个工厂,不再需要根据产品类型而挑选工厂
            Factory factory = new Factory();
            IProduct product = factory.Produce(part);
            Console.WriteLine("生产了一个产品:" + product.GetName());
            return product;
        }
    }
}

Program.cs

using System;

namespace ReflectionFactory
{
    class Program
    {
        static void Main(string[] args)
        {
            // output : 生产了一个产品:柱子
            IProduct pillar = FactoryManager.GetProduct(RoomParts.Pillar);
            // output : 生产了一个产品:屋顶
            IProduct roof = FactoryManager.GetProduct(RoomParts.Roof);
            // output : 生产了一个产品:窗户
            IProduct window = FactoryManager.GetProduct(RoomParts.Window);
            Console.Read();
        }
    }
}