当前位置:  开发笔记 > 编程语言 > 正文

抽象工厂设计模式

如何解决《抽象工厂设计模式》经验,为你挑选了2个好方法。

我正在为我的公司开发一个内部项目,项目的一部分是能够将XML文件中的各种"任务"解析为稍后要运行的任务集合.

因为每种类型的Task都有许多不同的相关字段,所以我认为最好用一个单独的类来表示每种类型的Task.

为此,我构建了一个抽象基类:

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个案例)开关来选择要实例化的子类.我希望我能在这里做一些多态的技巧来清理这个方法.

有什么建议?



1> DevelopingCh..:

我用反射来做到这一点.您可以创建一个基本上扩展的工厂,而无需添加任何额外的代码.

确保你有"使用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了,而且你也可以自己保存一个移动的东西来维护.



2> Tim Williscr..:

创建每个类的"Prototype"实例,并将它们放在工厂内的哈希表中,并将XML中的字符串作为键.

所以CreateTask只是通过哈希表中的get()来找到正确的Prototype对象.

然后在上面调用LoadFromXML.

你必须将类预先加载到哈希表中,

如果你想要它更自动......

您可以通过在工厂中调用静态寄存器方法来使类"自行注册".

将调用寄存器(带有构造函数)放在Task子类的静态块中.然后你需要做的就是"提及"类来运行静态块.

然后,任务子类的静态数组就足以"提及"它们.或者使用反射来提及类.

推荐阅读
乐韵答题
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有