zondag 10 maart 2013

Fluent Factory Method with Lambda's

In a previous article I showed you the Fluent Interface / Fluent Builder pattern. If you want to build a nice factory method you can use that pattern. But there's another option; factory with lambda expressions. then you can wrtite a factory method that you can use like this:


var validator = ValidatorFactory.New(config =>
      {
         config.HasName("Test");
         config.UseThatValidator();
       });

validator.Validate();


How does it work?

In this example we have two validators that implement the IValidator interface:



public interface IValidator
{
   void Validate();
}


public class ThisValidator : IValidator
{
   private string _name;

   public void Validate()
   {
      // Do something
   }
}


public class ThatValidator : IValidator
{
   private string _name;

   public void Validate()
   {
      // Do something
   }
}


Next we need a Configurator that can be used the the factory later:



public class ValidatorConfigurator
{
}

As you can see ThisValidator and ThatValidator have a name, so we need to have a way to configure that name. Let's add a method to the ValidatorConfigurator to set the name:



public class ValidatorConfigurator
{
   internal string _name;


   public ValidatorConfigurator HasName(string name)
   {
      _name = name;
      return this;
   }

}


This is the factory that we'll be using:



public static class ValidatorFactory

{
   public static IValidator New()
   {
   }
}




At this stage we can only call the New() method of the factory:

var validator = ValidatorFactory.New();



Add a lambda expression

We can't write a lambda expression as parameter of the New() method. How do we fix that? The easiest way is to add an Action with the Configuration as type:


public static class ValidatorFactory

{
   public static IValidator New(Action<ValidatorConfigurator> applySettings)
   {
   }
}



And this is what we can do with the factory now:

var validator = ValidatorFactory.New(x=>x.HasName("BestValidatorEver"));



Create a validator in the Factory

The New() method of the factory does nothing now. So we won't get a valid Validator back. Let's add some code to the New() method:


public static class ValidatorFactory

{
   public static IValidator New(Action<ValidatorConfigurator> applySettings)
   {
      // We need to have an instance of ValidatorConfigurator
      var validatorConfigurator = new ValidatorConfigurator();

      // Apply the settings to the instance of ValidatorConfigurator
      applyConfiguration(validatorConfigurator);

      // Let the Configurator create a Validator
      return validatorConfigurator.CreateValidator();
   }
}





Create a validator in the Configurator

In the factory above the Create() method of the ValidatorConfigurator was called. Let's write the code for that method:


internal IValidator CreateValidator()
{
   IValidator validator = new ThisValidator();
   validator.Name = this._name;

   return validator;
}



Conclusion

If we run this code:

var validator = ValidatorFactory.New(x=>x.HasName("BestValidatorEver"));

We get an instance of ThisValidator with the name BestValidatorEver. It's obvious that we need to expand the code so that you can choose between ThisValidator or ThatValidator. But that isn't to hard now, right?


Geen opmerkingen:

Een reactie posten