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个角色)
- 检查对象是否处于特定状态(来自一组状态)
- isOwner&(状态==11 | |状态==13 | |状态==14)
- !!(isOwner&isReceiver&status==12)
首先我想到了装饰图案。我有一个错误消息处理程序对象,可以用特定的错误消息修饰它。一个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();
}
}