Refactoring to State/Strategy
page 3 of 4
by Brian Mains
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 21893/ 38

Introduction to State/Strategy

Using the example of the class in Listing 1, the state/strategy pattern will move each parameter check into its own object, instead of creating a separate method for it.  The key to implementing the state/strategy pattern is to have a base class (ParameterCheck) that the objects in the pattern will derive from.  Below is a diagram of what this relationship will look like.

Figure 1

Each object will override the IsValid method in ParameterCheck to provide a more specific validation check.  The State/Strategy pattern works in this way, using inheritance to provide a means to add unlimited number of derived classes.  Both the State and Strategy pattern works like this; however, state is often used for representing a state object and strategy is often used for an algorithm of sorts.  Compare the following ParameterCheck definition over the previous code sample above.

Listing 2

public abstract class ParameterCheck
{
  public abstract bool IsValid(object data, object argument);
}

That is quite a difference.  ParameterCheck is now providing an interface that all derived types must implement and so most of the actual processing is now present in the concrete implementations TypeParameterCheck, NullableParameterCheck, etc.  To see what it looks like, the following is the definition of TypeParameterCheck.

Listing 3

public class TypeParameterCheck: ParameterCheck
{
  public override bool IsValid(object data, object argument)
  {
    if (!argument is Type)
      throw new ArgumentException("The argument type is not valid");
 
    return (data.GetType().IsAssignableFrom((Type)argument));
  }
}

The following is the definition of NullableParameterCheck, which takes a boolean value stating whether to ensure that a value is null or to ensure it is not null, based on the value of the parameter.

Listing 4

public class NullableParameterCheck: ParameterCheck
{
  public override bool IsValid(object data, object argument)
  {
    bool mustBeNulls;
 
    if (argument == null)
      mustBeNulls = false;
    else
      argument = (bool)argument;
 
    if (mustBeNulls)
      return (data == null);
    else
      return (data != null);
  }
}

Any number of derivatives can be added.  For instance, assuming that we wanted to add the ability to validate based on a list of values, we can do.

Listing 5

public class ValuesRangeParameterCheck: ParameterCheck
{
  public override bool IsValid(object data, object argument)
  {
    if (!argument is object[])
      throw new ArgumentException("The argument must be an array");
 
    List < object > values = new List < object > ((object[])argument);
    return values.Contains(data);
  }
}

And the list could go on, based on whatever requirements we may have.  Inheritance allows the ability to create N number of parameter checks without us having to have a definite list.  However, there has to be a means to expose each one, so at some point they need to be defined.  A common way is to create a custom configuration section, which can have an array of parameter check class references.  This is a similar concept to the membership element, which has a list of providers that it contains.  An alternative to this is to use a Factory method, which can take a string, enum, or some other object that uniquely references the correct parameter check.


View Entire Article

User Comments

No comments posted yet.






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-03-29 3:56:12 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search