4

在下面的代码中,我想根据另一个类的类型返回派生类,这是一种更优雅的方式。

            if (option_ is Rectangle)
            {
                modelInputs = new Foo();
            }
            else if (option_ is Circle)
            {
                modelInputs = new Bar();
            }
            else if (option_ is Triangle)
            {
                modelInputs = new Bar2();
            }
4

5 回答 5

8

让 Rectangle、Circle 和 Triangle 实现 IHasModelInput:

interface IHasModelInput
{
    IModelInput GetModelInput();
}

那么你可以做

IModelInput modelInputs = option_.GetModelInput();
于 2008-10-28T02:57:41.200 回答
3

我的意见:你的“不优雅”的方式很好。它简单,易读并且可以完成工作。

让 Rectangle、Circle 和 Triangle 通过IHasModelInput实现必要的工厂函数是可行的,但它有设计成本:您现在已经将这组类与 IModelInput 类集(Foo、Bar 和 Bar2)耦合。他们可能在两个完全不同的图书馆,也许他们不应该知道彼此。

下面是一个更复杂的方法。它为您提供了能够在运行时配置工厂逻辑的优势。

    public static class FactoryMethod<T>  where T : IModelInput, new()
    {
        public static IModelInput Create()
        {
            return new T();
        }
    }

    delegate IModelInput ModelInputCreateFunction();

    IModelInput CreateIModelInput(object item)
    {

        Dictionary<Type, ModelInputCreateFunction> factory = new Dictionary<Type, ModelInputCreateFunction>();


        factory.Add(typeof(Rectangle), FactoryMethod<Foo>.Create);
        factory.Add(typeof(Circle),    FactoryMethod<Bar>.Create);
        // Add more type mappings here




        IModelInput modelInput;
        foreach (Type t in factory.Keys)
        {
            if ( item.GetType().IsSubclassOf(t) || item.GetType().Equals(t))
            {
                modelInput = factory[t].Invoke();
                break;
            }
        }
        return modelInput;
    }

但接着问一个问题:你更愿意读哪一本?

于 2008-10-28T03:49:07.570 回答
1

您可以将输入和输出放在哈希表中,或者将创建每个类的类型存储在您创建的每个类中,然后使用 Activator.CreateInstance 进行工厂操作:

Hashtable ht = new Hashtable();
ht.Add(typeof(Rectangle), typeof(Bar));
ht.Add(typeof(Square), typeof(Bar2));

modelInputs = Activator.CreateInstance(ht[option.GetType()]);

无论哪种方式,Activator.CreateInstance 都是使工厂在 .NET 中工作的一种非常酷的方式。享受并明智地使用我赋予你的力量,孩子。

于 2008-10-28T04:02:12.160 回答
0

如果允许,您可以将类型与“option_”相关联,然后创建它的实例。

于 2008-10-28T02:56:05.930 回答
0

当我想在运行时将字符串转换为类型时,我通常使用这样的工厂方法,我使用将字符串映射到类型的字典。

就像最近的一个项目中的这样:

public class TaskFactory
{
    private Dictionary<String, Type> _taskTypes = new Dictionary<String, Type>();

    public TaskFactory()
    {
        // Preload the Task Types into a dictionary so we can look them up later
        foreach (Type type in typeof(TaskFactory).Assembly.GetTypes())
        {
            if (type.IsSubclassOf(typeof(CCTask)))
            {
                _taskTypes[type.Name.ToLower()] = type;
            }
        }
    }

    public CCTask CreateTask(XmlElement task)
    {
        if (task != null)
        {
            string taskName = task.Name;
            taskName =  taskName.ToLower() + "task";

            // If the Type information is in our Dictionary, instantiate a new instance of that task
            Type taskType;
            if (_taskTypes.TryGetValue(taskName, out taskType))
            {
                return (CCTask)Activator.CreateInstance(taskType, task);
            }
            else
            {
                throw new ArgumentException("Unrecognized Task:" + task.Name);
            }                               
        }
        else
        {
            return null;
        }
    }
}
于 2008-10-28T04:05:55.680 回答