【问题标题】:Which design pattern to use and how for survey platform?调查平台使用哪种设计模式以及如何使用?
【发布时间】:2023-03-11 03:29:01
【问题描述】:

我正在尝试解决调查系统的最佳架构以及要使用的设计模式。 我们有以下类型的问题:

  • 可能有一个正确答案 - 下拉菜单或单选按钮
  • 多项选择 - 复选框
  • 是/否 - 带有是/否的单选按钮
  • 短文本
  • 长文本
  • 数字 - 例如什么时候……?
  • 正确的顺序 - 例如按正确顺序排列答案

我想要绘图 API 和验证 API 所以我想出了主要用于绘画的“桥梁图案”。但是我缺少一些东西。

我尝试的是这样的:

public abstract class Question : IDrawable, IValidatable
{
    protected readonly IQuestionFormatter questionFormatter;
    protected readonly IQuestionValidator validator;

    public string Title { get; set; }

    public Question(IQuestionFormatter questionFormatter, IQuestionValidator validator)
    {
        this.questionFormatter = questionFormatter;
        this.validator = validator;
    }

    public abstract void Draw();

    public abstract bool Validate();

}

    public interface IQuestionValidator
{
    bool ValidateQuestion(IEnumerable<string> userInput, 
                          IEnumerable<string> questionAnswers);
}

    public interface IQuestionFormatter
{
    string FormatQuestion(string title, IEnumerable<string> options);
}

然后我为 MultipleChoiceQuestion、OnePossibleAnswerQuestion 和 ShortAnswer 创建 RefinedAbstractions。问题是 MultipleChoiceQuestion 可能有许多正确答案和许多 UserInput

public class MultipleChoiceQuestion : Question
{
    public List<string> Options { get; set; } = new List<string>();
    public List<string> Answers { get; set; } = new List<string>();
    public List<string> UserInput { get; set; } = new List<string>();

    public MultipleChoiceQuestion(IQuestionFormatter questionFormatter, IQuestionValidator validator) : base(questionFormatter, validator)
    {
    }

    public override void Draw()
    {
        var result = questionFormatter.FormatQuestion(Title, Options);
        Console.WriteLine(result);
    }

    public override bool Validate()
    {
        return validator.ValidateQuestion(UserInput, Answers);
    }
}

OnePossibleAnswerQuestion 有许多答案,但只有一个用户输入

 public class OnePossibleAnswerQuestion : Question
{
    public string UserInput { get; set; }
    public string Answer { get; set; }
    public List<string> Options { get; set; } = new List<string>();

    public OnePossibleAnswerQuestion(IQuestionFormatter questionFormatter, IQuestionValidator validator) : base(questionFormatter, validator)
    {
    }

    public override void Draw()
    {
        var result = questionFormatter.FormatQuestion(Title, Options);
        Console.WriteLine(result);
    }

    public override bool Validate()
    {
        return validator.ValidateQuestion(new List<string> { UserInput }, new List<string> { Answer });
    }
}

ShortAnswer 有一个答案和一个用户输入。我不确定如何创建设计。 公共课 ShortAnswer : 问题 { 公共字符串用户输入{得到;放; } 公共字符串答案 { 得到;放; }

    public ShortAnswer(IQuestionFormatter questionFormatter, IQuestionValidator validator) : base(questionFormatter, validator)
    {
    }

    public override void Draw()
    {
        var result = questionFormatter.FormatQuestion(Title, new List<string> { "" });
        Console.WriteLine(result);
    }

    public override bool Validate()
    {
        return validator.ValidateQuestion(new List<string> { UserInput }, new List<string> { Answer });
    }
}

但是当我到达 OnePossibleAnswerQuestion 或 ShortAnswer 时,.Validate() .Draw() 开始闻起来了。可能我定义了错误的接口?

我的目标是拥有这样的东西:

    List<Question> questions = new List<Question>();

    // ... add some questions using Builder or Factory Design Pattern

    // draw the questions
    foreach (var question in questions)
    {
        question.Draw();
    }

    // validate the questions
    foreach (var question in questions)
    {
        question.Validate();
    }

您能帮我解决我想念的东西以及如何组合这些类吗?我是否使用了错误的设计模式?

提前致谢!

【问题讨论】:

  • 您的实际问题是什么?我不能从阅读你的问题中说出来。
  • 真正的问题是如何按照一些设计模式为调查平台设计类。问题的类型有很多共同点,但同时它们又是如此不同。它们的不同主要在于 .Draw() 和 .Validate() 方法。我试图利用桥接模式,但代码对我来说很臭 - 更具体地说是在 .Draw() 和 .Validate() 方法中。
  • 首先:将业务逻辑与表示分离。任何Draw() 方法都不应该存在于发生验证或任何与业务相关的类中。尝试获取您的类层次结构并在控制台应用程序中重用它。
  • 你是对的,但是验证呢?

标签: c# asp.net design-patterns architecture


【解决方案1】:

1) 让验证者处理问题,但不处理输入和答案:

this.validator.Validate(this);

2) 让您的格式化程序使用问题而不是标题和选项:

this.formatter.Format(this);

= 现在您可以在基类中移动您的 Validate() 和 Draw() 方法,而不是在每个问题类型中实现。此外,您将能够提供具有新属性的新问题类型,例如音频或图片。

3) 为了使它有用,您需要使用问题渲染器而不是格式化程序。如果您决定将输入从文本控制台更改为 HTML 页面怎么办?

4) 您也可以为问题添加 GetInput() 方法,使其具有如下内容:

List<Question> questions = new List<Question>();

// draw the questions
foreach (var question in questions)
{
    question.Draw();
    question.GetInput();
    question.Validate();
}

或者您可以直接在按钮点击时 Draw() 问题并调用 Validate()。

【讨论】:

  • 您好,感谢您的贡献:) 我们越来越近了,但我有一些注意事项: - 将(this) 作为Question 类型的参数传递我只能访问基类Question特性。例如,我无法检查具有字段UserInputShortAnswer 的有效性。 - 另一个问题是Question 类型NumberQuestion 应该有UserInput 作为Int32
  • 没关系,因为您的格式化程序“知道”您的问题是什么类型。这就是为什么你只是通过'this'。您的格式化程序会将 Question 转换为 NumericQuestion,因为它继承自此基类。
猜你喜欢
  • 2014-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-06
  • 1970-01-01
相关资源
最近更新 更多