Tuesday, July 21, 2009

Using the Decorator Pattern to Evaluate Complex Conditions

As part of a project on which I am currently working, I recently had to create a Condition class to be used in defining and evaluating complex groupings of logical and arithmetic conditions. After considering the matter for a while, I decided that this would be an ideal situation for using the Decorator Pattern.

For those of you who may not be familiar with this pattern, http://www.dofactory.com/Patterns/PatternDecorator.aspx defines it as a means of attaching additional responsibilities to an object dynamically. The most common example found is some variation of incrementally adding cost components to some base entity, such as toppings on pizza or condiments in coffee. An example of this, using cars as the base entity, may be found at http://www.codeproject.com/KB/architecture/PatternsIntro_Decorator.aspx . It’s time for a change!

In this blog post I present a console application in which the user is allowed to enter an integer (let’s call it ‘x’), and the application then determines whether or not it satisfies the following complex condition:
1 <= x <= 5 OR x > 7
This application represents a major simplification of the task I was asked to perform in my current project.

First let’s look at the main method of the application:


It is fairly easy to observe that the work-horse of this application is the Condition class. The first instantiation of this class defines the condition ‘x >= 1’. The second instantiation defines the condition ‘x <= 5’ and also AND’s the two conditions together. Thus, it establishes the necessary ‘environment’ for evaluating ‘1 <= x <= 5’. Similarly, the final instantiation defines the condition ‘x > 7’ and OR’s this result with the result of the second evaluation: 1 <= x <= 5 OR x > 7.

How is this accomplished? Let’s begin by looking at the two constructors found in the Main method. The 3-parameter constructor specifies the variable whose value is to be evaluated, the value to which it is to be compared, and the type of comparison to be made. The options for the latter are defined in the ArithmeticOperator enumeration:

The five-parameter constructor first specifies the three values found in the former. In addition, it specifies a second condition to be evaluated in conjunction with the ‘current’ one, and the logical operator to be used when jointly evaluating the two conditions:


Going back to the Main method, notice that the final result is obtained by merely retrieving the ConditionResult property value for the last Condition instance in the chain. This is some powerful property!

The logic of the property ‘getter’ is fairly easy to understand. It merely evaluates the current condition, and then, if the ‘rightSide’ condition has been specified, either AND’s or OR’s the current result with the result of evaluating the other condition.
The TestCondition method is nothing but simple arithmetic comparison of the variable to be evaluated against the specified comparison value:


Thus, the Decorator Pattern provides a very powerful, simple-to-apply way of evaluating complex logical expressions.

NOTE: If any of the above images are difficult to see, just double-click them to view a larger representation.

No comments:

Post a Comment