抽象工厂设计模式

2024-01-04

我正在为我的公司开发一个内部项目,该项目的一部分是能够将 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 个案例)开关来选择要实例化的子类。我希望我可以在这里使用某种多态技巧来清理这个方法。

有什么建议吗?


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

确保您有“using 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,并且还可以为自己节省维护的移动部分。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

抽象工厂设计模式 的相关文章

  • 如何使 Windows 窗体的关闭按钮不关闭窗体但使其不可见?

    该表单有一个 NotifyIcon 对象 当用户单击 关闭 按钮时 我希望表单不关闭而是变得不可见 然后 如果用户想再次查看该表单 可以双击系统托盘中的图标 如果用户想关闭表单 可以右键单击该图标并选择 关闭 有人可以告诉我如何使关闭按钮不
  • 是否可以强制 XMLWriter 将元素写入单引号中?

    这是我的代码 var ptFirstName tboxFirstName Text writer WriteAttributeString first ptFirstName 请注意 即使我使用 ptFirstName 也会以双引号结束 p
  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • 未解决的包含:“cocos2d.h” - Cocos2dx

    当我在 Eclipse 中导入 cocos2dx android 项目时 我的头文件上收到此警告 Unresolved inclusion cocos2d h 为什么是这样 它实际上困扰着我 该项目可以正确编译并运行 但我希望这种情况消失
  • 指针问题(仅在发布版本中)

    不确定如何描述这一点 但我在这里 由于某种原因 当尝试创建我的游戏的发布版本进行测试时 它的敌人创建方面不起作用 Enemies e level1 3 e level1 0 Enemies sdlLib 500 2 3 128 250 32
  • C 预处理器库

    我的任务是开发源分析工具C程序 并且我需要在分析本身之前预处理代码 我想知道什么是最好的图书馆 我需要一些重量轻 便于携带的东西 与其推出自己的 为什么不使用cpp这是的一部分gcc suite http gcc gnu org onlin
  • 如果使用 SingleOrDefault() 并在数字列表中搜索不在列表中的数字,如何返回 null?

    使用查询正数列表时SingleOrDefault 当在列表中找不到数字时 如何返回 null 或像 1 这样的自定义值 而不是类型的默认值 在本例中为 0 你可以使用 var first theIntegers Cast
  • Cython 和类的构造函数

    我对 Cython 使用默认构造函数有疑问 我的 C 类 Node 如下 Node h class Node public Node std cerr lt lt calling no arg constructor lt lt std e
  • WPF TabControl,用C#代码更改TabItem的背景颜色

    嗨 我认为这是一个初学者的问题 我搜索了所有相关问题 但所有这些都由 xaml 回答 但是 我需要的是后台代码 我有一个 TabControl 我需要设置其项目的背景颜色 我需要在选择 取消选择和悬停时为项目设置不同的颜色 非常感谢你的帮助
  • Web API - 访问 DbContext 类中的 HttpContext

    在我的 C Web API 应用程序中 我添加了CreatedDate and CreatedBy所有表中的列 现在 每当在任何表中添加新记录时 我想填充这些列 为此目的我已经覆盖SaveChanges and SaveChangesAsy
  • 从路径中获取文件夹名称

    我有一些路c server folderName1 another name something another folder 我如何从那里提取最后一个文件夹名称 我尝试了几件事 但没有成功 我只是不想寻找最后的 然后就去休息了 Thank
  • 如何衡量两个字符串之间的相似度? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 给定两个字符串text1 and text2 public SOMEUSABLERETURNTYPE Compare string t
  • 将 xml 反序列化为类,list<> 出现问题

    我有以下 XML
  • C++ 复制初始化和直接初始化,奇怪的情况

    在继续阅读本文之前 请阅读在 C 中 复制初始化和直接初始化之间有区别吗 https stackoverflow com questions 1051379 is there a difference in c between copy i
  • 控制到达非 void 函数末尾 -wreturn-type

    这是查找四个数字中的最大值的代码 include
  • 如何让Gtk+窗口背景透明?

    我想让 Gtk 窗口的背景透明 以便只有窗口中的小部件可见 我找到了一些教程 http mikehearn wordpress com 2006 03 26 gtk windows with alpha channels https web
  • C - 直接从键盘缓冲区读取

    这是C语言中的一个问题 如何直接读取键盘缓冲区中的数据 我想直接访问数据并将其存储在变量中 变量应该是什么数据类型 我需要它用于我们研究所目前正在开发的操作系统 它被称为 ICS OS 我不太清楚具体细节 它在 x86 32 位机器上运行
  • 为什么我收到“找不到编译动态表达式所需的一种或多种类型。”?

    我有一个已更新的项目 NET 3 5 MVC v2 到 NET 4 0 MVC v3 当我尝试使用或设置时编译出现错误 ViewBag Title财产 找不到编译动态表达式所需的一种或多种类型 您是否缺少对 Microsoft CSharp
  • 限制C#中的并行线程数

    我正在编写一个 C 程序来生成并通过 FTP 上传 50 万个文件 我想并行处理4个文件 因为机器有4个核心 文件生成需要更长的时间 是否可以将以下 Powershell 示例转换为 C 或者是否有更好的框架 例如 C 中的 Actor 框
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我

随机推荐

  • 使用 SWT 时的 Java SwingWorker

    我有一个问题如下 我编写了一个简单的简约应用程序 它使用 SWT 作为 GUI 在特定选项卡中 它显示一个通过 REST Api 调用填充信息的表格 另外 我还有另一种方法将此表导出到 CSV 文件中 这绝对没问题 现在我需要某种自动更新
  • Adobe After Effects 扩展脚本 - 如何从命令行运行脚本并传入参数?

    我正在尝试从命令行运行 Adob e AE 扩展脚本 我使用 r 参数 可以很好地运行脚本 但是 是否可以向脚本传递参数 就像 如果我从命令行运行这个 C gt C Program Files Adobe Adobe After Effec
  • NSMutableArray containsObject 返回 true,但它不应该

    我发现了类似的问题 但是 containsObject没有像我预期的那样工作 我的问题是NSMutableArray containsObject方法在不应该返回 true 时返回 true 当尝试生成随机唯一颜色并添加到数组时 检查是否存
  • 如何以编程方式将 Factor-bundle 与 browserify 一起使用?

    我想使用 Factor bundle 来查找 browserify 入口点的公共依赖项并将它们保存到单个公共包中 https www npmjs org package factor bundle https www npmjs org p
  • 如何使用 servlet 中的保存文件对话框?

    我试图让用户将 servlet 中的数据保存为 CSV 文件 最初我只是找到他们的桌面来放置文件 但此路线的权限会被拒绝 所以我想询问用户他们想要将文件保存在哪里 据我所知 我无法在 servlet 中使用 Swing API 因为 Tom
  • 点在函数中获取“脚本”

    我的 PowerShell 配置文件变得有点麻烦 我发现我并不总是使用其中的所有内容 我想减小我的个人资料的大小并加快启动时间 但我仍然希望能够访问这些功能相对地当我需要它们时很快 有没有办法 点源 https en wikipedia o
  • Cuda char* 变量赋值

    这是本文所选答案的后续问题 cuda程序的输出不是预期的 https stackoverflow com questions 6561005 output of cuda program is not what was expected 6
  • 清除 HTML 画布中形状下的像素

    我正在使用 HTML 画布和 javascript 并且需要清除通过关闭路径创建的形状下方的所有像素 例如 我正在使用flot http code google com p flot 并且我想制作圆角 为此 我首先需要通过在角的顶部绘制一条
  • Maven 创建一个空文件夹而不是获取适当的 .jar

    Maven 创建一个空文件夹而不是获取适当的 jar 我有一个由 3 个模块组成的项目 其中一个模块是其他两个模块的公共部分 当两个模块生成 WAR 文件时 第三个模块必须生成一个 JAR 该 JAR 应该嵌入到其他两个 WEB INF l
  • Magento CMS 错误:前端控制器达到 100 次路由器匹配迭代

    当我通过 CMS 在管理中 创建页面时 一切看起来都很好 但是当我尝试访问前端中的页面时 我得到一个带有错误的空白页面 Front controller reached 100 router match iterations 0 app c
  • NoSQL 的用例[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 NoSQL 最近在我们行业受到了广泛的关注 我真的很感兴趣人们对它在关系数据库存储上的最佳用例的看法 什么会促使开发人员认为特定数据集更适合 N
  • 在 Git 中的根提交之前插入非空提交?

    我有一个问题 请各位好心人指教 我有一个现有的 git 存储库 并且由于各种原因 我不会在这里讨论 我正在尝试创建一个 ROOT 提交 假设这是我的 git 提交历史记录 ROOT C1 lt C2 lt C3 lt C4 lt C5 lt
  • jQuery:如何制作一个清晰的按钮?

    我有一个搜索字段 我需要一个清晰的按钮 我目前有按钮 但我不知道该怎么做 我有 6 个文本字段 2 个组合框和 2 个多选列表 如何在一个清除函数中清除所有这些 我知道 HTML 方式 但我使用 Grails 并且 type reset 不
  • 如何使用 Chart.js 更改 Barchart 中仅一列的颜色

    js http www chartjs org docs bar chart http www chartjs org docs bar chart 我正在使用基本示例 HTML
  • 是否可以在单手柄 jQuery UI 滑块上设置固定的静态范围?

    本质上我要做的是一个用于一堆日期的单句柄 jQuery UI 滑块 选择的日期范围始终为两周 我想做的只是显示从两周范围的开始日期 即句柄驻留的日期 开始的一个范围 该范围不必是功能性的 只是显示 向前两周 这个范围是固定的 例如 如果句柄
  • 从 Eclipse 远程部署 Tomcat Web 应用程序

    出于开发和测试目的 我想将我的 web 应用程序从 eclipse 部署到远程 tomcat 服务器 这可能吗 如果没有 我应该如何设置我的开发环境以实现顺利 轻松的远程部署 如果您可以远程访问 Tomcat 管理器应用程序 那么您可以使用
  • 让用户选择他希望程序使用多少个线程

    我想让一个程序读取 txt 文件的每一行 并对每一行执行一些操作 我希望用户能够选择线程 因此如果他选择 10 个线程 那么程序将能够同时在 10 行上执行某些操作 假设文本文件包含 1 000 000 行 我该怎么办 这就是我实际上所拥有
  • 如何确定 connectNative 是失败还是成功

    我已成功将我的扩展连接到我们的本机主机 var pulse tracker port chrome runtime connectNative com cloudfactory pulsetracker 但我如何知道连接是否成功呢 无论连接
  • Xcode 5“缺少编译器规范 LLVM 4.2”错误

    我目前正在尝试在 Xcode 5 中构建我的项目 构建失败并出现错误 依赖性分析错误 missing compiler specification
  • 抽象工厂设计模式

    我正在为我的公司开发一个内部项目 该项目的一部分是能够将 XML 文件中的各种 任务 解析为稍后运行的任务集合 由于每种类型的任务都有许多不同的关联字段 因此我决定最好用单独的类来表示每种类型的任务 为此 我构造了一个抽象基类 public