TheChaseMan's Frenetic SoapBox

Always looking for better ways to do things...

Strategy Pattern: Today, Tomorrow, and C# 3.0

New Page 3

The Strategy (GoF) pattern is basically: giving the ability to provide an algorithm (implementation) to another class so it can handle a specific operation. The best anology I have seen was in MSDN magazine when they talked about using IComparer. You've probably already used this pattern without know its formal name. If you take a look at the code below we have a Person class and a PersonCollection. The SortByName method on the PersonCollection class wraps an ArrayList.Sort() call. ArrayList.Sort lets you provide an IComparer implementation...or strategy. To be clear, I've derived my own class from IComperer called "Strategy". This contains a very simple "strategy" algorithm which is defaulting to use the String.Compare operation so we can sort alphabetically by name. The call to this.InnerList.Sort passes an instance of the Strategy class. Quite simply, this is the GoF strategy pattern...

public class Person {

    //should be properties, but to be brief we'll use fields

    public string Name;

    public int Age;

 

    public Person(string name, int age) {

        Name = name;

        Age = age;

    }

}

 

public class PersonCollection : CollectionBase {

    class Strategy : IComparer {

        public int Compare(object x, object y) {

            Person px = x as Person;

            Person py = y as Person;

            return String.Compare(px.Name, py.Name);

        }

    }

 

    public void SortByName() {

        this.InnerList.Sort(new Strategy());

    }

 

    public void Add(Person value) {

        this.InnerList.Add(value);

    }

}

 

class Program

{

    static void Main(string[] args) {

        PersonCollection people = new PersonCollection();

        people.Add(new Person("Bubba", 20));

        people.Add(new Person("Al", 22));

        people.Add(new Person("Cooter", 99));

        people.SortByName();

 

        //prints: Al, Bubba, Cooter

        foreach(Person p in people)

            Console.WriteLine(p.Name);

    }

}

Note that in C# 2.0, which will RTM in about 2 weeks, you can simplify the above example quite a bit using anonymous methods. It turns out the to sort a generic List, you can pass in a System.Comparison delegate like so...

static void Main(string[] args) {

 

List<Person> people = new List<Person>();

people.Add(new Person("Bubba", 20));

people.Add(new Person("Al", 22));

people.Add(new Person("Cooter", 99));

 

//use anonymous method here...

people.Sort(delegate(Person x, Person y) {

                return String.Compare(x.Name, y.Name);

            });

 

 

//prints: Al, Bubba, Cooter

foreach(Person p in people)

    Console.WriteLine(p.Name);

}

While I'm on the subject, in C# 3.0 you can make this example even more simple using lambdas. The whole strategy pattern for sorting because a single lambda expression like so...

static void Main(string[] args) {

 

    List<Person> people = new List<Person>();

    people.Add(new Person("Bubba", 20));

    people.Add(new Person("Al", 22));

    people.Add(new Person("Cooter", 99));

   

    //use the C# 3.0 lambda feature

    people.Sort(((x, y) => String.Compare(x.Name, y.Name)));

   

 

    //prints: Al, Bubba, Cooter

    foreach(Person p in people)

        Console.WriteLine(p.Name);

 

}


Digg!

posted on Sunday, October 23, 2005 2:43 PM

Feedback

No comments posted yet.