我有一个名为 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);
}
}
对我来说看起来很干净。 :)