.NET类设计问题

2024-04-30

我有一个名为 Question 的类,它有一个名为 Type 的属性。基于这种类型,我想以特定的方式将问题呈现为html(多项选择=单选按钮,多个答案=复选框等...)。我从一个 RenderHtml 方法开始,该方法根据问题类型调用子方法,但我认为将渲染逻辑分离到实现接口的各个类中可能会更好。然而,由于此类使用 NHibernate 持久保存到数据库中,并且接口实现依赖于属性,因此我不确定如何最好地布局该类。

有问题的班级:

public class Question
{
    public Guid ID { get; set; }
    public int Number { get; set; }
    public QuestionType Type { get; set; }
    public string Content { get; set; }
    public Section Section { get; set; }
    public IList<Answer> Answers { get; set; }
}

基于 QuestionType 枚举属性,我想呈现以下内容(仅作为示例):

<div>[Content]</div>
<div>
   <input type="[Depends on QuestionType property]" /> [Answer Value]
   <input type="[Depends on QuestionType property]" /> [Answer Value]
   <input type="[Depends on QuestionType property]" /> [Answer Value]
   ...
</div>

目前,我在一个名为 RenderHtml() 的函数中有一个很大的 switch 语句来完成脏工作,但我想将其移至更干净的地方。我只是不知道怎么做。

有什么想法吗?

编辑:感谢大家的回答!

我最终选择了使用以下界面的策略模式:

public interface IQuestionRenderer
{
    string RenderHtml(Question question);
}

以及以下实现:

public class MultipleChoiceQuestionRenderer : IQuestionRenderer
{
    #region IQuestionRenderer Members

    public string RenderHtml(Question question)
    {
        var wrapper = new HtmlGenericControl("div");
        wrapper.ID = question.ID.ToString();
        wrapper.Attributes.Add("class", "question-wrapper");

        var content = new HtmlGenericControl("div");
        content.Attributes.Add("class", "question-content");
        content.InnerHtml = question.Content;
        wrapper.Controls.Add(content);

        var answers = new HtmlGenericControl("div");
        answers.Attributes.Add("class", "question-answers");
        wrapper.Controls.Add(answers);

        foreach (var answer in question.Answers)
        {
            var answerLabel = new HtmlGenericControl("label");
            answerLabel.Attributes.Add("for", answer.ID.ToString());
            answers.Controls.Add(answerLabel);

            var answerTag = new HtmlInputRadioButton();
            answerTag.ID = answer.ID.ToString();
            answerTag.Name = question.ID.ToString();
            answer.Value = answer.ID.ToString();
            answerLabel.Controls.Add(answerTag);

            var answerValue = new HtmlGenericControl();
            answerValue.InnerHtml = answer.Value + "<br/>";
            answerLabel.Controls.Add(answerValue);
        }

        var stringWriter = new StringWriter();
        var htmlWriter = new HtmlTextWriter(stringWriter);
        wrapper.RenderControl(htmlWriter);
        return stringWriter.ToString();
    }

    #endregion
}

修改后的 Question 类使用内部字典,如下所示:

public class Question
{
    private Dictionary<QuestionType, IQuestionRenderer> _renderers = new Dictionary<QuestionType, IQuestionRenderer>
    {
        { QuestionType.MultipleChoice, new MultipleChoiceQuestionRenderer() }
    };

    public Guid ID { get; set; }
    public int Number { get; set; }
    public QuestionType Type { get; set; }
    public string Content { get; set; }
    public Section Section { get; set; }
    public IList<Answer> Answers { get; set; }

    public string RenderHtml()
    {
        var renderer = _renderers[Type];
        return renderer.RenderHtml(this);
    }
}

对我来说看起来很干净。 :)


一般来说,每当您看到类型或枚举上的开关时,这意味着您可以将对象替换为“类型” - 换句话说,这是一个例子多态性 http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming.

这实际上意味着您将为每个问题类型创建一个不同的类并覆盖RenderHTML()功能。每个问题对象将负责知道它应该输出什么输入类型。

好处是您可以删除 switch 语句并生成良好的基于​​ OO 的代码。缺点是您需要为每个问题类型添加一个类(在本例中影响最小。)

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

.NET类设计问题 的相关文章

随机推荐

  • “未定义变量”通知

    我对 php 很陌生 所以我确信这是一个简单的过程 我收到这个错误 Notice Undefined variable conn in C Dev Webserver Apache2 2 htdocs EclipsePHP thecock
  • Google Checkout 和 Android Market 之间的 API 级别差异是否有记录?

    序言 这个问题已经过时了 不再有 Google Checkout 和 API Android Market 使用 Google Checkout 进行付费应用程序销售 Google Checkout 有相当广泛的 API Android M
  • 带有 return 语句的 Julia @parallel for 循环

    如何在满足条件时立即返回所有工作人员的函数中编写并行 for 循环 IE 像这样的东西 function test n sync parallel for i in 1 1000 statement if condition return
  • 编辑 CMakeLists.txt 以使用 -fPIC 进行编译

    我正在尝试为名为 libnifalcon 的 NOVINT Falcon 安装驱动程序 我使用 cmake 创建 make 文件 但是当我运行 make 时出现错误 Linking CXX shared library lib libnif
  • R 中添加额外常量的累积乘法

    我是 R 新手 正在努力解决以下累积乘法与添加额外常量的组合 我希望在数据框中实现以下目标 Variable X Variable Y Variable Z X1 Y1 Y1 X1 Z1 X2 Y2 Z1 Y2 X2 Z2 X3 Y3 Z2
  • 使用 Angular 上传文件时 HttpPostedFileBase 为 null

    我将 Angular 与 MVC 结合使用 当我想上传文件时 HttpPostedFileBase一片空白 html
  • gdb 通过指向错误的代码行显示不正确的回溯

    我们可以通过在源代码中包含多个中止调用 用非常简单的示例重现此问题 在下面的示例代码中 我们在不同条件下总共有四个中止调用 但是当我们使用优化标志 O3 进行编译时 我们只能看到一个中止调用的调试信息 因此 在这四个中止调用中发生崩溃时 g
  • 如何在grails中自定义spring security插件登录页面

    我尝试在 Spring Security Core 3 1 1 中自定义登录页面 但没有成功 我在views目录中创建了一个登录目录 并在登录目录中创建了一个auth gsp 并将我的自定义表单放在那里 这是代码
  • 为什么这个简单的 MySQL 查询不返回该行?

    我在表中有一行users与用户名test 但由于某种原因 此查询返回空结果集 SELECT id FROM users WHERE username test AND id null 但是 如果我删除 id null段 查询返回结果id 1
  • P12 证书“数据不足”错误

    我试图使用安全地连接到端点 p12文件 但我不断收到以下错误 tls common js 136 c context loadPKCS12 pfx Error not enough data at Error native at Objec
  • 为什么我使用的 KnownType 属性是错误的?

    我正在尝试反序列化来自 google api 的 json 响应 所以我想我应该定义几个类来帮助它 DataContract public class DetectionResult ResponseData DataMember Name
  • ExtGWT 与 ExtJS [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 当开始一个新的应用程序时 您会权衡哪些因素来决定是使用 ExtGWT 还是 ExtJS 对于同时了解 Javascript 和 Java 的程序
  • 朴素分类器 matlab

    在 matlab 中测试朴素分类器时 即使我在相同的样本数据上进行训练和测试 我也会得到不同的结果 我想知道我的代码是否正确 是否有人可以帮助解释这是为什么 dimensionality reduction columns 6 U S V
  • 在鼠标悬停时在右侧或左侧扬声器上播放声音[重复]

    这个问题在这里已经有答案了 我正在尝试使用 PyQt5 用 python 编写小程序 该程序将有两个按钮 中间有一个标签 当鼠标移到标签上时 我想调用一个 def 以便更改按钮的颜色并从特定扬声器 左或右 播放声音 我尝试了 pygame
  • 如何在 Visual Studio 2017 项目(新的 .csproj 文件格式)中设置“OutputPath”,而不会使目标框架扰乱解析的路径?

    Setting OutputPath在新的 Visual Studio 2017 项目格式中 会自动在路径中添加目标框架 例如 如果我在项目文件中设置了这些
  • Ansible 权限问题

    我正在尝试将当前用户添加到系统中的某个组 然后执行需要该组权限的命令 我的剧本是这样的 name Add this user to RVM group sudo true user state present name vagrant ap
  • 绘制顶部有函数线的直方图

    我正在尝试使用 SciPy 进行统计 使用 matplotlib 进行绘图 在 Python 中进行一些分布绘图和拟合 我在创建直方图等方面运气很好 seed 2 alpha 5 loc 100 beta 22 data ss gamma
  • 了解 C# 中的自签名证书

    最近我遇到了这个c 代码 var dn new X500DistinguishedName CN appSettings CommonName OU appSettings OrganizationalUnit X500Distinguis
  • 第一响应者设置不正确

    我有一个分组表视图 并尝试在用户按 Enter 时将新的第一响应者设置为文本字段 这对我来说不是什么新鲜事 在我进行一些不相关的更改之前我的代码可以工作 但现在却不能了 当我设置第一响应者时 我有一个指向正确文本字段的指针 但没有任何反应
  • .NET类设计问题

    我有一个名为 Question 的类 它有一个名为 Type 的属性 基于这种类型 我想以特定的方式将问题呈现为html 多项选择 单选按钮 多个答案 复选框等 我从一个 RenderHtml 方法开始 该方法根据问题类型调用子方法 但我认