Home > Patterns and Practices > Strategy Pattern

Strategy Pattern

Strategy Pattern

Problem:

There is need to manage several different implementations of what is conceptually them same algorithm. Assume you are writing a QuickSort algorithm which can sort any object. Here the conceptual algorithm (QuickSort) remains the same. The sort rules are different for different objects. But that’s not the case with the finer details of implementation. For example implementation for integers and strings it is pretty straight forward. For Customer object it could be based on Customer Name, for Order object it is based on OrderDate or probably Sale amount.

 

Solution:

Here the variation is in the Sort strategy, it depends on business rules. Hence factor this out into a separate object. Also program to an interface never to an implementation. So make this an interface. That gives us the IComparer interface. The actual class which implements the QuickSort can act as the context object.

 

Strategy follows this approach:

In a slightly varying family of algorithms,

Ø        Find what varies (Sort strategy in our case) and encapsulate it in a class of its own (CustomerComparer, OrderComparer in our case).

Ø        Contain this class in another class (Context class in our class, EntitySorter in our class).

The implementation turns out like this.

                                     

public interface IComparer

{

            int Compare(EntityBase x, EntityBase y);

}

public class EntityBase

{

 

}

public class Customer : EntityBase

{

            public Customer(string firstName,string lastName, string customerNumber)

            {

                        this.firstName = firstName;

                        this.lastName = lastName;

                        this.customerNumber = customerNumber;

            }

 

            private string firstName;

            private string lastName;

            private string customerNumber;

 

            public string FirstName

            {

                        get

                        {

                                    return firstName;

                        }

            }

            public string LastName

            {

                        get

                        {

                                    return lastName;

                        }

            }

            public string CustomerNumber

            {

                        get

                        {

                                    return customerNumber;

                        }

            }

}

public class Order : EntityBase

{

            public Order(string orderNumber, DateTime orderDate)

            {

                        this.orderNumber = orderNumber;

                        this.orderDate = orderDate;

            }

            private string orderNumber;

            private DateTime orderDate;

            public string OrderNumber

            {

                        get

                        {

                                    return orderNumber;

                        }

            }

            public DateTime OrderDate

            {

                        get

                        {

                                    return orderDate;

                        }

            }

}

 

public class OrderComparer : IComparer

{

            public int Compare(EntityBase x, EntityBase y)

            {

                        Order o1 = (Order)x;

                        Order o2 = (Order)y;

 

                        return o1.OrderDate.CompareTo(o2.OrderDate);

            }

}

 

public class CustomerComparer : IComparer

{

            public int Compare(EntityBase x, EntityBase y)

            {

                        Customer c1 = (Customer)x;

                        Customer c2 = (Customer)y;

 

                        return (c1.FirstName + c1.LastName).CompareTo(c2.FirstName + c2.LastName);

            }

}

public class EntitySorter

{

            private EntityBase[] arrayToSort;

            private IComparer comparer;

           

            public EntitySorter(EntityBase[] arrayToSort, IComparer comparer)

            {

                        this.arrayToSort = arrayToSort;

                        this.comparer = comparer;

            }

 

            public void QuickSort(int left, int right)

            {

                        if(left >= right) return;

 

                        int i = left;

                        int j = right + 1;

 

                        EntityBase pivot = arrayToSort[left];

 

                        // Swap elements >= pivot on the left side

                        // with elements <= pivot on the right side

                        while(true)

                        {

                                    do

                                    {

                                                i++;

                                    }

                                    while(comparer.Compare(arrayToSort[i], pivot) < 0);

                       

                                    do

                                    {

                                                j–;

                                    }

                                    while(comparer.Compare(arrayToSort[i], pivot) > 0);

 

                                    if(i >= j) break;

                       

                                    // Swap(arrayToSort[i], arrayToSort[j]);

                                    EntityBase temp;

                                    temp = arrayToSort[i];

                                    arrayToSort[i] = arrayToSort[j];

                                    arrayToSort[j] = temp;                                      

                       

                        }

 

                        // place pivot

                        arrayToSort[left] = arrayToSort[j];

                        arrayToSort[j] = pivot;

                       

                        QuickSort(left, j-1);

                        QuickSort(j+1, right);

            }

}

 

The GoF Class Structure Diagram

 

Note: .NET Framework uses this pattern for the IComparer interface used for Sort method on the Array and ArrayList classes.

Advertisements
  1. No comments yet.
  1. November 19, 2010 at 11:00 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: