Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Strategy Design Pattern

I want to be able to gather several pieces of validation entities, all sharing same interface. This is what I came up with:

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?
 }
}

What is the best way to pass User / Campaign so that I can loop strategies and check IsValid?

like image 720
Guy Z Avatar asked Aug 24 '26 09:08

Guy Z


1 Answers

Here's how I'd do it:

// 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);
    }
}

After that, you can call ValidationFactory.IsValid(myObject); and if the type is in the factory static constructor, it will give you true/false.

The validation factory is doing a kind of DI/IOC thing, i.e. you could use Ninject, Castle etc to achieve mapping a type to a validator type.

You could do things dynamically or differently without having to build the dictionary in the same way - look at the generic type parameter of the interface the validator implements, or search for IValidationStrategy<>-based classes and again look at the generic type parameter. But the above is quick and simple.

Is there a reason you want separate validator classes?

like image 140
Kieren Johnstone Avatar answered Aug 27 '26 00:08

Kieren Johnstone



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!