March 2008 Entries

The strategy pattern is typically used when your programmer's algorithm should be interchangeable with different variations of the algorithm. For example, if you have code that sorts array, under certain circumstances, you might want to create QuickSort and under other circumstances, you might want to create Merge Sort.

The strategy pattern is usually implemented by declaring an abstract base class with an algorithm method, which is then implemented by inheriting concrete classes. At some point in the code, it is decided what concrete strategy is relevant; it would then be instantiated and used wherever relevant.

Following example shows how a ArrayList with diffrent sort algorithms.


using System;
using System.Collections;
using NUnit.Framework;

namespace DesignPatterns
{
    // Strategy class: SortStrategy
    // Define the general interface common to all supported algorithms
    public abstract class SortStrategy
    {
        public abstract void Sort(ArrayList list);
    }

    // Concrete class QuickSort
    public class QuickSort : SortStrategy
    {
        public override void Sort(ArrayList list)
        {
            // Sort the list using a quicksort algorithm
        }
    }

    // Concrete class MergeSort
    public class MergeSort : SortStrategy
    {
        public override void Sort(ArrayList list)
        {
            // Sort the list using a mergesort algorithm
        }
    }

    // Context class
    public class SortedList
    {
        private ArrayList list = new ArrayList();
        private SortStrategy sortstrategy;

 public SortedList(SortStrategy sortstrategy)
        {
            this.sortstrategy = sortstrategy;)
   
 }
       
        public void Add(string name)
        {
            list.Add(name);
        }

        public void Sort()
        {
            sortstrategy.Sort(list);
        }
    }

    [TestFixture]
    public class StrategyClassTestFixture
    {
        [Test]
        public void TestSortedList()
        {
            SortedList sortedList = new SortedList(new QuickSort());

            sortedList.Add("mitchel");
            sortedList.Add("gregg");
            sortedList.Add("steve");
            sortedList.Add("rob");

        }
    }
}

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

since i have already posted basic ContraVariance in delegate, i am not going to go thru the same again, those of you who had missed my earlier post can refer here

here is an example of using generics with contravariance

namespace ContravarianceWithGenerics
{
    public interface IEquity
    {
        string ToString();
        string Save();
    }

    //base class
    abstract class Equity : IEquity
    {
        int _price;

        public Equity(int Price)
        {
            _price = Price;
        }
        public override string ToString()
        {
            return GetType().Name + " : " + _price;
        }

        #region IEquity Members


        public virtual string Save()
        {
            return "Called from Base Class";
        }

        #endregion
    }
    //derived
    class Stock : Equity
    {
        public Stock(int Price)
            : base(Price)
        {

        }

        public override string Save()
        {
            return "Called from Stock Class";
        }
    }

    //derived
    class Bond : Equity
    {
        public Bond(int Price)
            : base(Price)
        {

        }

        public override string Save()
        {
            return "Called from Bond Class";
        }
    }

    class EquityBusinessImplementation<T> where T: Equity, IEquity
    {
        public delegate void SellNotify(T b);

        public void EquitySaleReport(Equity e)
        {
            Console.WriteLine("Report of sale is " + e);
            Console.WriteLine(e.Save() );
        }
        public SellNotify sellNotifyDlg;

        public void Sell(T s)
        {
            if (null != sellNotifyDlg)
            {
                sellNotifyDlg(s);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            EquityBusinessImplementation<Stock> s =
                new EquityBusinessImplementation<Stock>();
            s.sellNotifyDlg += s.EquitySaleReport;
            s.Sell(new Stock(100));

            EquityBusinessImplementation<Bond> b =
                new EquityBusinessImplementation<Bond>();
            b.sellNotifyDlg += b.EquitySaleReport;
            b.Sell(new Bond(1000));
        }
    }
}

Happy programming !!!

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

A generic class that uses parameterized types, like MyBase<T>, is called an open-constructed generic. A generic class that uses no parameterized types, like MyBase<int>, is called a closed-constructed generic.

You may derive from a closed-constructed generic; that is, you may inherit a class named MyDerived from another class named MyBase, as in:


public class MyDerived<T> : MyBase1<int>

You may derive from an open-constructed generic, provided the type is parameterized.

For example:

public class MyDerived<T> : MyBase<T> is valid, but


public class MyDerived<T> : MyBase<Y> is not valid since Y is also a parameterized type.

Note: Non-generic classes may derive from closed-constructed generic classes, but not from open-constructed generic classes. That is,

public class MyDerived : MyBase<int> is valid, but


public class MyDerived : MyBase<T> is not valid.

-------

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

A generic class allows you to write your class without committing to any type, yet allows the user of your class, later on, to indicate the specific type to be used. While this gives greater flexibility by placing some constraints on the types that may be used for the parameterized type, you gain some control in writing your class. Let's look at an example:

Example 1. The need for constraints: code that will not compile


public static T Max<T>(T op1, T op2)
{
        if (op1.CompareTo(op2) < 0)
                return op1;
        return op2;
}


The code in Example 1 will produce a compilation error:

Error 1 'T' does not contain a definition for 'CompareTo'

Assume I need the type to support the CompareTo() method. I can specify this by using the constraint that the type specified for the parameterized type must implement the IComparable interface. Example 2 has the code:

Example 2. Specifying a constraint


public static T Max<T>(T op1, T op2) where T : IComparable
{
        if (op1.CompareTo(op2) < 0)
                return op1;
        return op2;
}

In Example 2, I have specified the constraint that the type used for parameterized type must inherit from (implement) IComparable. The following are some of the other constraints may be used:


where T : struct                   type must be a value type (a struct)
where T : class                   type must be reference type (a class)
where T : new()                  type must have a no-parameter constructor
where T : class_name      type may be either class_name or one of its
                                              sub-classes (or is below class_name
                                              in the inheritance hierarchy)

where T : interface_name  type must implement the specified interface
You may specify a combination of constraints, as in: where T : IComparable, new(). This says that the type for the parameterized type must implement the IComparable interface and must have a no-parameter constructor.

------

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati