【问题标题】:Multiple Strategy Design Pattern多策略设计模式
【发布时间】:2012-09-05 21:13:44
【问题描述】:

我希望能够收集多个验证实体,它们都共享相同的界面。这是我想出的:

public interface Ivalidateable
{
  bool IsValid(IValidateParam param);
}

public interface IValidateParam
{

}

public abstract EmployeeStrategy: Ivalidateable
{
  public abstract bool IsValid(User user); 
}

public abstract SpreadStrategy: IValidateable
{
 public abstract bool IsAvlid(Campaign campaign);
}

public class User: IValidateParam
{}

public class Campaign: IValidateParam
{}

public EmployeeTypeStragtegy: EmployeeStrategy, IValidateable
{
 public bool IsValid(User user)
 {
  if  (new[]{'e',a','b}.Contains(user.userId.first().toString()))
  return true;

  return false; 
 }
}

public TrailSpreadStrategy: SpreadStrategy, IValidateable
{
 public bool IsValid(Campaign campaign)
 {
  //logic goes here
 }
}

public EvenpreadStrategy: SpreadStrategy:, IValidateable
{
 public bool IsValid(Campaign campaign)
 {
  //logic goes here
 }
}

public class ValidationFactory
{
 private static List<IValidateable> stragtegies;

 static ValidationFactory
 {
  strategies = new List<IValidateable>();
  strategies.Add(new EmployeeTypeStragtegy());
  strategies.Add(new TrailSpreadStrategy());
 }

 public bool IsValid(//Need to pass User/Campaign)
 {
  //what do I do here?
 }
}

传递 User / Campaign 以便我可以循环策略并检查 IsValid 的最佳方法是什么?

【问题讨论】:

  • 您有两种验证广告系列的策略,都将被执行还是有一些标准可以选择正确的?
  • 每种类型(用户/广告系列)只有一种...我只是想展示声明多个类型的想法

标签: c# asp.net-mvc validation design-patterns strategy-pattern


【解决方案1】:

我会这样做:

// campaign object class, and it's separate validator logic

public class Campaign
{
}

public class CampaignValidator : IValidationStrategy<Campaign>
{
    public bool IsValid(Campaign test)
    {
        return true;
    }
}

// framework stuff

public interface IValidationStrategy<T>
{
    bool IsValid(T test);
}

public static class ValidationFactory
{
    private readonly static Dictionary<Type, object> _typeValidators;

    static ValidationFactory()
    {
        _typeValidators = new Dictionary<Type, object>();
        _typeValidators[typeof(Campaign)] = new CampaignValidator();
    }

    public static bool IsValid<T>(T obj)
    {
        return ((IValidationStrategy<T>)_typeValidators[typeof(T)]).IsValid(obj);
    }
}

之后,你可以调用ValidationFactory.IsValid(myObject);,如果类型在工厂静态构造函数中,它会给你true/false。

验证工厂正在做一种 DI/IOC 的事情,即您可以使用 Ninject、Castle 等来实现将类型映射到验证器类型。

您可以动态或不同地做事,而不必以相同的方式构建字典 - 查看验证器实现的接口的泛型类型参数,或搜索基于 IValidationStrategy&lt;&gt; 的类并再次查看泛型类型范围。但是上面的方法又快又简单。

您有需要单独的验证器类的原因吗?

【讨论】:

  • 我想将它们分开,因为每个验证对象都有一个不同的对象
  • 是的,我明白了,但是为什么不在每个对象本身上包含一个 IsValid 呢? :)
  • 我想我明白了!谢谢!我想遍历它们并为每个策略调用 IsValid,这就是为什么我对每个策略都有 IsValid。
  • 顺便说一句,如何使用您的建议在工厂的 IsValid 中使用循环验证所有字典策略?
【解决方案2】:

我建议看看FluentValidation 的嵌套和集合验证功能。这应该可以在没有额外的工厂和接口的情况下正常工作 - 如果您的策略包含对您想要与它们一起验证的其他实体的引用。

【讨论】:

    【解决方案3】:

    这个怎么样?

    更改您的所有 IsValid 以使用此原型(用户用户、广告系列活动),例如:

    public EmployeeTypeStragtegy: EmployeeStrategy, IValidateable
    {
     public bool IsValid(User user, Campaign campaign)
     {
        return (new char[]{'e','a','b'}.Contains(user.userId.first().toString());
     }
    }
    

    然后按适当的类型处理每个,这样它们都接受相同的参数。然后:

    public bool IsValid(User user, Campaign campaign)
     {
       bool valid;
    
       foreach (IValidateable iv in strategies)
       {
          if (!iv.IsValid(user, campaign))
              valid = false;
       }
    
       // This returns true if all are valid, false if not (not sure if this is the logic you expect)
       return valid;
     }
    

    【讨论】:

    • 我想做这样的事情: public bool IsValid(User user, Campaign Campaign) { return strategy.All(s=>s.IsValid(//???)) }
    • 所以您想提供 1 个用户和 1 个广告系列并循环遍历所有策略以查看它们是否对任何一个都有效,具体取决于类型?
    • 完全正确!!!如果策略基于 Employee,它将使用用户,如果是 SpreadStrategy,它将使用活动
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 2015-09-15
    相关资源
    最近更新 更多