工厂基于Typeof或是

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

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

有Rectangle,Circle和Triangle实现IHasModelInput:

 interface IHasModelInput { IModelInput GetModelInput(); } 

那么你可以做到

 IModelInput modelInputs = option_.GetModelInput(); 

我的观点:你的“不优雅”的方式很好。 它简单易读,可以完成任务。

让Rectangle,Circle和Triangle通过IHasModelInput实现必要的工厂函数会起作用,但它有一个设计成本:你现在已经将这组类与IModelInput类集合(Foo,Bar和Bar2)相结合。 他们可能在两个完全不同的图书馆,也许他们不应该彼此了解。

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

  public static class FactoryMethod where T : IModelInput, new() { public static IModelInput Create() { return new T(); } } delegate IModelInput ModelInputCreateFunction(); IModelInput CreateIModelInput(object item) { Dictionary factory = new Dictionary(); factory.Add(typeof(Rectangle), FactoryMethod.Create); factory.Add(typeof(Circle), FactoryMethod.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; } 

但随后问一个问题:你宁愿阅读哪一个?

您可以将输入和输出放在Hashtable中,或者存储在您创建的每个类中创建每个类的类型,然后使用Activator.CreateInstance来执行factoryin’:

 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中运行的一种非常酷的方式。 儿子,享受,并明智地使用我给你的力量。

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

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

像最近的一个项目一样:

 public class TaskFactory { private Dictionary _taskTypes = new Dictionary(); 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; } } }