实现规范设计模式以检查一系列字符串属性

时间:2014-01-09 10:39:49

标签: c# oop design-patterns

我可以使用规范设计模式来改进以下场景吗?我很难看到如何实现它?

谢谢,

if (!string.IsNullOrEmpty(obj.Firstname) && !string.IsNullOrEmpty(obj.Lastname)
            && !string.IsNullOrEmpty(obj.Email)
            && !string.IsNullOrEmpty(obj.Username))
{
  // do something
}

1 个答案:

答案 0 :(得分:1)

当然,规范可以隐藏这个条件。但是,如果这是您的代码的唯一问题,并且仅在一个地方检查此条件,我将不会创建规范。即使重复此检查,我的第一个想法是避免处于无效状态的对象 - 即只是避免为此属性分配null值。如果不可能,那么您可以询问用户是否有效,而不是从用户获取值并在用户之外检查它们(Tell, Don't Ask Principle):

public bool IsValid // consider better name here
{
    get
    {
         return !String.IsNullOrEmpty(Firstname) &&
                !String.IsNullOrEmpty(Lastname) &&
                !String.IsNullOrEmpty(Email) &&
                !String.IsNullOrEmpty(Username);           
    }
}

但是如果您打算创建复杂的规范,或者您计划将它们传递给您的系统(例如将规范传递给存储库以获取某些特定对象),那么这是一个好主意。

定义规范界面(如果您想要更多规范,或者如果您想要模拟它们):

public interface ISpecification<T>
{
    bool IsSatisfiedBy(T value);
}

创建特定的规范(当然,名称可能更具体,如OvertimeWorkerSpecification,它会检查工人是否有加班时间):

public class UserSpecification : ISpecification<User>
{
    public bool IsSatisfiedBy(User user)
    {
        return !String.IsNullOrEmpty(user.Firstname) &&
               !String.IsNullOrEmpty(user.Lastname) &&
               !String.IsNullOrEmpty(user.Email) &&
               !String.IsNullOrEmpty(user.Username);
    }
}

假设用户看起来像:

public class User
{
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public string Email { get; set; }
    public string Username { get; set; }
}

用法很简单:

var spec = new UserSpecification();

// then pass your user to check if he satisfies specification
if (spec.IsSatisfiedBy(obj))
    // do something

// or filter users with specification
var validUsers = users.Where(spec.IsSatisfiedBy);

另外,我建议你阅读Martin Fowler撰写的非常好的Specifications文章。