【问题标题】:Implementing a Chain of Validations with their own confirmation dialogs?使用自己的确认对话框实现验证链?
【发布时间】:2012-06-13 20:25:21
【问题描述】:

我需要执行一系列验证,比如 ValidationA、ValidationB、ValidationC。

如果任何验证失败,则链无法立即验证。

只有在前一个验证条件通过后,才会执行每个后续验证。

如果验证条件失败,我需要向用户显示确认对话框,例如“你确定你要这么做吗?” — 如果用户说“是”,那么我们应该继续进行链中的下一个验证。如果用户在确认对话框中说“否”,那么我们可以立即失败。

什么是实现这个的好方法?

【问题讨论】:

  • 也许是时候标记答案了?

标签: algorithm design-patterns language-agnostic


【解决方案1】:

答案在 C# 中,但我希望它很清楚。这里最重要的是原始验证与 UI 分离。 OverridableValidator 是一个“UI 人”,它在构造函数中获取“逻辑人”,以及要显示给用户的消息。

interface IValidator<T>
{
    bool IsValid(T subject);
}

class OverridableValidator<T> : IValidator<T>
{
    readonly IValidator<T> _validator;
    readonly string _confirmOverrideMessage;

    public OverridableValidator(IValidator<T> validator, string confirmOverrideMessage)
    {
        _validator = validator;
        _confirmOverrideMessage = confirmOverrideMessage;
    }

    public bool IsValid(T subject)
    {
        if (_validator.IsValid(subject))
        {
            return true;
        }
        return MessageBox.Show(_confirmOverrideMessage, "Confirmation required", MessageBoxIcon.Question, MessageBoxButtons.YesNo) == DialogResult.Yes;
    }
}

class Person
{
    public int Age {get;set;}
    public int HeightInCentimeters {get;set;}
}

class MaturityValidator : IValidator<Person>
{
    public bool IsValid(Person guy)
    {
        return guy.Age >= 18;
    }
}

class HeightValidator : IValidator<Person>
{
    public bool IsValid(Person guy)
    {
        return guy.HeightInCentimeters < 120;
    }
}

void Main()
{
    var ageValidator = new OverridableValidator<Person>(new MaturityValidator(), "Do you want to sell him cigarettes?");
    var heightValidator = new OverridableValidator<Person>(new HeightValidator(), "Do you want to invite such a short person to your basketball team?");

    var validatedPerson = new Person() { Age = 15, HeightInCentimeters = 140 };
    var validatorsList = new[] {ageValidator, heightValidator};
    foreach (var validator in validatorsList)
    {
        if (!validator.IsValid(validatedPerson))
        {
            return; //validaton failed
        }
    }
    Console.WriteLine("This guy can smoke and play in NBA");
}

【讨论】:

    【解决方案2】:

    这样实现:

    (ValidationA || UserConfirmationA) && (ValidationB || UserConfirmationB) && (ValidationC || UserConfirmationC)
    

    其中 Validation 和 UserComfirmation 是函数,它们按照名称执行并返回布尔值。

    我假设 &amp;&amp;|| 是惰性的,这在大多数语言中都是如此。

    【讨论】:

    • 糟糕的设计。我什至害怕真正的代码看起来像……意大利面条地狱。
    【解决方案3】:

    除了 dzendras 所说的之外,看看 Chain of responsibility pattern 允许您动态添加验证器可能会对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-26
      • 1970-01-01
      • 2013-03-17
      • 2011-07-31
      • 2010-10-27
      • 1970-01-01
      • 1970-01-01
      • 2010-09-16
      相关资源
      最近更新 更多