Skip to content

利用反射实现工厂模式

需求

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

示例

RoomParts.cs

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

ProductAttribute.cs

csharp
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

csharp
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

csharp
using System;

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

Roof.cs

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

Window.cs

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

Pillar.cs

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

IFactory.cs

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

Factory.cs

csharp
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

csharp
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

csharp
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();
        }
    }
}

Page Layout Max Width

Adjust the exact value of the page width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the page layout
A ranged slider for user to choose and customize their desired width of the maximum width of the page layout can go.

Content Layout Max Width

Adjust the exact value of the document content width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the content layout
A ranged slider for user to choose and customize their desired width of the maximum width of the content layout can go.