Design patterns 验证场景所需的设计解决方案

Design patterns 验证场景所需的设计解决方案,design-patterns,architecture,validation,Design Patterns,Architecture,Validation,我想验证一些对象。验证分为两部分: 验证用户是否有权访问对象(特定权限已计算并存储在布尔值中,最多有4个角色) 检查对象是否处于特定状态(来自一组状态) 我有很多规则(实际上总共大约25条)需要验证,比如下面的规则: isOwner&(状态==11 | |状态==13 | |状态==14) !!(isOwner&isReceiver&status==12) 我将这些规则分散在几个方法中,一个方法中有4或5个规则。 如果一条规则失败,则不会检查其他规则。 我需要在使用此验证的每个方法中构

我想验证一些对象。验证分为两部分:

  • 验证用户是否有权访问对象(特定权限已计算并存储在布尔值中,最多有4个角色)
  • 检查对象是否处于特定状态(来自一组状态)
我有很多规则(实际上总共大约25条)需要验证,比如下面的规则:

  • isOwner&(状态==11 | |状态==13 | |状态==14)
  • !!(isOwner&isReceiver&status==12)
我将这些规则分散在几个方法中,一个方法中有4或5个规则。 如果一条规则失败,则不会检查其他规则。 我需要在使用此验证的每个方法中构造一个验证器(或设置一个已构造的验证器)

我正在寻找一种设计模式,它可以使构建一个验证对象的结构变得更容易。我的目标是能够提供特定的错误消息。例如,如果验证失败是因为用户没有权限,那么我想让他/她知道这一点。如果因为对象的状态而失败,那么我想显示它


首先我想到了装饰图案。我有一个错误消息处理程序对象,可以用特定的错误消息修饰它。一个decorator检查用户权限,另一个检查状态。但我构建验证器对象的顺序并不重要,因此没有使用装饰器模式的功能。(好吧,这是使用decorator的一大优势——混合装饰)。我认为连锁店可能更适合这种情况。。。?!?!对于此场景,您会推荐什么设计方案?

您应该使用此场景的策略模式,因为对于给定的用户角色(isOwner)和状态代码,您需要不同的算法。

与其考虑使用什么样的模式,不如考虑哪些对象有意义,以及它们的行为应该是什么

在本例中,您要做的是将对象传递给一系列规则。如果其中一条规则失败,则会触发一条消息,而其余规则不会被检查(是否正确)

如果是这样的话,您会注意到我们没有讨论的场景是数据传递给链中的所有规则。。。这表示一个命令链模式,而不是一个装饰器

另一方面,如果你想把它传递给所有的规则,我觉得它更像一个访问者模式


考虑理想的解决方案,然后确定模式。不要一开始就试图找到一个模式来应用。

我会使用一个责任链。您使对象通过该链。

使用策略(例如:要检查的列表或规则)+状态机(例如:带产量的枚举(.net))

类程序
{
公共类状态对象
{
公共虚拟int状态{get;set;}
}
公共抽象类规则
{
公共抽象结果检查(StateObject对象检查);
}
公共类DefaultAllow:规则
{
公共覆盖结果检查(StateObject对象被选中)
{
Console.WriteLine(“DefaultAllow:allow”);
返回结果。允许;
}
}
公共类DefaultDeny:规则
{
公共覆盖结果检查(StateObject对象被选中)
{
Console.WriteLine(“DefaultDeny:deny”);
返回结果。拒绝;
}
}
公共类DefaultState:规则
{
公共覆盖结果检查(StateObject对象被选中)
{
WriteLine(“DefaultState:state:{0}”,objectToBeChecked.state);
返回objectToBeChecked.State==1?Result.Allow:Result.Deny;
}
}
公共课策略
{
公共虚拟IEnumerable GetRules()
{
返回新列表()
{
新的DefaultAllow(),
新DefaultState()
};
}
}
公共类验证器
{
私有只读策略(private readonly Strategy);
公共验证器(策略)
{
_战略=战略;
}
公共IEnumerable进程(StateObject对象被选中)
{
foreach(_strategy.GetRules()中的规则)
收益返回规则。检查(objectToBeChecked);
}
}
公共类MyStateMachine
{
私有只读验证程序_验证程序;
私有StateObject _StateObject;
公共事件事件处理程序低;
公共事件处理程序;
公共事件事件处理程序OnError;
公共MyStateMachine(验证器验证器)
{
_验证器=验证器;
}
公共void Init(StateObject StateObject)
{
_stateObject=stateObject;
}
受保护的虚拟void Validate()
{
Result=Result.Allow;//默认值
foreach(在_validator.Process(_stateObject))中的结果r)
{
结果=r;
如果(r!=结果.允许)
打破
}
if(result==result.Allow)
通知(低);
else if(result==result.Deny)
通知(OnDeny);
else if(result==result.Error)
通知(OnError);
其他的
抛出新的NotSupportedException();
WriteLine(“结果:{0}”,
class Program
    {
        public class StateObject
        {
            public virtual int State { get; set; }
        }

        public abstract class Rule
        {
            public abstract Result Check(StateObject objectToBeChecked);

        }

        public class DefaultAllow : Rule
        {
            public override Result Check(StateObject objectToBeChecked)
            {
                Console.WriteLine("DefaultAllow: allow");
                return Result.Allow;
            }
        }

        public class DefaultDeny : Rule
        {
            public override Result Check(StateObject objectToBeChecked)
            {
                Console.WriteLine("DefaultDeny: deny");
                return Result.Deny;
            }
        }

        public class DefaultState : Rule
        {
            public override Result Check(StateObject objectToBeChecked)
            {
                Console.WriteLine("DefaultState: state: {0}", objectToBeChecked.State);
                return objectToBeChecked.State == 1 ? Result.Allow : Result.Deny;
            }
        }

        public class Strategy
        {

            public virtual IEnumerable<Rule> GetRules()
            {
                return new List<Rule>()
                           {
                               new DefaultAllow(),
                               new DefaultState()
                           };
            }
        }

        public class Validator
        {
            private readonly Strategy _strategy;

            public Validator(Strategy strategy)
            {
                _strategy = strategy;
            }

            public IEnumerable<Result> Process(StateObject objectToBeChecked)
            {
                foreach (Rule rule in _strategy.GetRules())
                    yield return rule.Check(objectToBeChecked);
            }

        }

        public class MyStateMachine
        {
            private readonly Validator _validator;
            private StateObject _stateObject;

            public event EventHandler OnAllow;
            public event EventHandler OnDeny;
            public event EventHandler OnError;

            public MyStateMachine(Validator validator)
            {
                _validator = validator;
            }

            public void Init(StateObject stateObject)
            {
                _stateObject = stateObject;
            }

            protected virtual void Validate()
            {
                Result result = Result.Allow; // default 

                foreach (Result r in _validator.Process(_stateObject))
                {
                    result = r;
                    if (r != Result.Allow)
                        break;
                }

                if (result == Result.Allow)
                    Notify(OnAllow);
                else if (result == Result.Deny)
                    Notify(OnDeny);
                else if (result == Result.Error)
                    Notify(OnError);
                else
                    throw new NotSupportedException();

                Console.WriteLine("Result: {0}", result);
            }


            private void Notify(EventHandler handler)
            {
                if (handler != null)
                    handler.Invoke(_stateObject, EventArgs.Empty);
            }


            public void ChangeState(int prevState, int newState)
            {
                if (prevState != _stateObject.State)
                    throw new InvalidStateException();

                _stateObject.State = newState;

                Validate(); // maybe this,  maybe before assign a new state 
            }
        }

        public class InvalidStateException : Exception { }

        public enum Result { Allow, Deny, Error }


        static void Main(string[] args)
        {
            Strategy defaultStrategy = new Strategy();
            Validator ruleChecker = new Validator(defaultStrategy);
            MyStateMachine stateMachine = new MyStateMachine(ruleChecker);

            StateObject objectToBeChecked = new StateObject();
            stateMachine.Init(objectToBeChecked);

            stateMachine.ChangeState(objectToBeChecked.State, 1);
            stateMachine.ChangeState(objectToBeChecked.State, 2);


            Console.ReadLine();
        }
    }