我正在为我的公司进行内部项目,该项目的一部分是能够将XML文件中的各种“任务”解析为一组任务,以便稍后运行。
因为每种任务类型都有大量不同的关联字段,所以我认为最好用单独的类来代表每种任务类型。
为此,我构造了一个抽象基类:
public abstract class Task
{
public enum TaskType
{
// Types of Tasks
}
public abstract TaskType Type
{
get;
}
public abstract LoadFromXml(XmlElement task);
public abstract XmlElement CreateXml(XmlDocument currentDoc);
}
每个任务都从该基类继承,并且包括从传入的XmlElement中创建自身并将其序列化回XmlElement所需的代码。
一个基本的例子:
public class MergeTask : Task
{
public override TaskType Type
{
get { return TaskType.Merge; }
}
// Lots of Properties / Methods for this Task
public MergeTask (XmlElement elem)
{
this.LoadFromXml(elem);
}
public override LoadFromXml(XmlElement task)
{
// Populates this Task from the Xml.
}
public override XmlElement CreateXml(XmlDocument currentDoc)
{
// Serializes this class back to xml.
}
}
然后,解析器将使用与此类似的代码来创建任务集合:
XmlNode taskNode = parent.SelectNode("tasks");
TaskFactory tf = new TaskFactory();
foreach (XmlNode task in taskNode.ChildNodes)
{
// Since XmlComments etc will show up
if (task is XmlElement)
{
tasks.Add(tf.CreateTask(task as XmlElement));
}
}
所有这些工作都非常出色,使我可以使用基类传递任务,同时保留每个任务具有单独类的结构。
但是,我对TaskFactory.CreateTask的代码不满意。此方法接受XmlElement,然后返回适当的Task类的实例:
public Task CreateTask(XmlElement elem)
{
if (elem != null)
{
switch(elem.Name)
{
case "merge":
return new MergeTask(elem);
default:
throw new ArgumentException("Invalid Task");
}
}
}
因为我必须解析XMLElement,所以我使用了一个巨大的开关(在实际代码中为10-15种情况)来选择要实例化的子类。我希望可以在这里进行某种多态技巧来清理此方法。
有什么建议吗?
最佳答案
我使用反射来做到这一点。
您可以创建一个基本上可以扩展的工厂,而无需添加任何额外的代码。
确保您已“使用System.Reflection”,将以下代码放入实例化方法中。
public Task CreateTask(XmlElement elem)
{
if (elem != null)
{
try
{
Assembly a = typeof(Task).Assembly
string type = string.Format("{0}.{1}Task",typeof(Task).Namespace,elem.Name);
//this is only here, so that if that type doesn't exist, this method
//throws an exception
Type t = a.GetType(type, true, true);
return a.CreateInstance(type, true) as Task;
}
catch(System.Exception)
{
throw new ArgumentException("Invalid Task");
}
}
}
另一个观察结果是,您可以使此方法成为静态方法,并将其卡在Task类之外,这样就不必重新创建TaskFactory,还可以节省动手的维护工作。
关于c# - 抽象工厂设计模式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27294/