Archive

Archive for November, 2005

Singleton Pattern

November 30, 2005 6 comments

Singleton

Context

You are building an application in C#. You need a class that has only one instance, and you need to provide a global point of access to the instance.

 

Solution:

public class Singleton

{

            private static Singleton instance;

           

            public static Singleton Instance

            {

                        if(instance == null)

                        {

                                    instance = new Singleton();

                        }

                        return instance;

            }

 

            private Singleton() { }

}

 

This is not thread-safe. When thread 1 is checking instance is null, it finds it null. Say now thread 2 is given control. Thread 2 also decides instance is null. Now say thread 1 takes control and creates a new instance returns it to the application. Thread 2 takes control now creates another instance overwrites the old one and returns the new instance to the applcication, now the application has atleast two instances of Singleton thus defeating the purpose. Oops!

 

A thread-safe Solution:

 

public sealed class Singleton

{

private static readonly Singleton instance = new Singleton();

 

private Singleton(){}

 

public static Singleton Instance

{

get

{

return instance;

}

            }

}

 

The CLR ensures that the singleton is thread-safe. In the static constructor / class constructor a new instance is initialized. That’s it. This is the simplest pattern. Bye till the next installment.

 

The GoF Class Structure Diagram:

Note: In .NET Framework DBNull.Value is a singleton class.

Builder Pattern

November 30, 2005 2 comments

Builder Pattern

Problem:

You are building a complex object step by step and you want to separate creation from the internal representation of the object so that you can have multiple representations of the same object. For example you have an Order object which has the customer details (like customer name, customer address), order level details (like order date, order value, ship method, shipping address) and order item details (number of products, product details). You should be able to export the order object as an Xml document for your inventory application and as Html, Rich Text or Plain Text e-Mail for the customer.

 

Solution:

The builder pattern comes to the rescue here. The GoF Class Structure diagram:

Domain Example:

 

public class Order

{

            private string customerName;

            private Address customerAddress;

            private DateTime orderDate;

            private Decimal orderValue;

            private ShipMethod shipMethod;

            private Address shippingAddress;

            private ArrayList orderLineItems;

 

            public string CustomerName {

get  { return customerName; }

set { customerName = value; }

}

public Address CustomerAddress {

            get { return customerAddress; }

            set { customerAddress = value; }

}

public DateTime OrderDate {

            get { return orderDate; }

            set { orderDate = value; }

}

// And so on for other properties

 

public string ExportOrder(OrderExporter exporter)

{

            exporter.ExportCustomerDetails(customerName, customerAddress);

            exporter.ExportOrderLevelDetails(orderDate, orderValue, shipMethod, shippingAddress);

            exporter.ExportOrderLineItems(orderLineItems)

            return exporter.ToString();

}

}

 

public abstract class OrderExporter

{

            public abstract void ExportCustomerDetails(string customerName, Address customerAddress);

            public abstract void ExportOrderLevelDetails(DateTime orderDate, Decimal orderAmount, ShipMethod shippingMethod, Address shippingAddress)

            public abstract void ExportOrderLineItem(OrderLineItem item);

            public void ExportOrderLineItems(ArrayList orderLineItems)

            {

            foreach (OrderLineItem item in orderLineItems)

            {

                        ExportOrderLineItem(item);

            }         

            }         

}

 

public class XmlExporter : OrderExporter

{

            // Implementation of the builder methods to build an Xml String

            public override string ToString()

            {

                        // return Xml String representation

}

}

 

public class HtmlExporter: OrderExporter

{

            // Implementation of the builder methods to build an Html String

            public override string ToString()

            {

                        // return Html String representation

}

}

 

public class RtfExporter: OrderExporter

{

            // Implementation of the builder methods to build an Rtf String

            public override string ToString()

            {

                        // return Rtf String representation

}

}

 

public class PlainTextExporter : OrderExporter

{

            // Implementation of the builder methods to build an Plain Text String

            public override string ToString()

            {

                        // return Plain Text String representation

}

}

 

In this example the Order class acts as the director, the OrderExporter class is the AbstractBuilder, the XmlExporter, HtmlExporter, RtfExporter and the PlainTextExporter classes are the ConcreteBuilders.

 

Donno where it might be used in the .NET Framework. Bye till the next installment. 

Template Method

November 30, 2005 1 comment

Template Method Pattern

Problem:

You have a consistent set of steps to follow but individual steps may have different implementations. For example in our project we had implemented this pattern. We had two windows services reading items (in chunks) from a queue, process each item and mark the item as processed. Thus the base algorithm for processing is same.

 

Messages = Read

For Each Message In Messages

            Try

            Begin Transaction

            Parse Message

                            Process Message

            Mark Message as Processed

         Commit Transaction

            Catch Exception

                        Rollback Transaction

                        Move to Failed

            End Try

Next Message

 

But each service had to read from different data stores.

 

Solution:

So we implemented the above algorithm in a “template method” in the base class from the individual services derive from.

 

Each operation Read, Parse Message, Process Message, Mark Message As Processed, Move To Failed was an abstract method in the base class. These were implemented in the derived classes. The template method was itself a non virtual method (not overridable).

 

The GoF class structure diagram:

Note:

In .NET Framework,

When dealing with custom controls, there are two general types: controls that combine the functionality of several existing controls (called composite controls), and controls with a unique visual representation.

Regardless of which style of custom control you choose, you don’t have to write any code to handle the functionality that’s common to all controls, like loading and saving ViewState at the right time, allowing PostBack events to be handled, and making sure the control lifecycle events are raised in the correct order. The main algorithm for how a control should be loaded, rendered, and unloaded is contained in the control base class.

The specifics of your particular control are handled at well-defined places in the control algorithm (the CreateChildControls or Render methods). This is an example of the Template Method pattern.

 

As simple as that. Bye for now, rest in next 😉

 

Iterator Pattern

November 30, 2005 1 comment
Iterator Pattern
This notes uses “Implementing Custom Data Bindable Classes: IEnumerable” from the O’Reilly ondotnet site http://www.ondotnet.com/lpt/a/3957 and some other article which I don’t know where I gleaned it from 😉
 
Problem:

Access the contents of a collection sequentially without exposing the implementation of the collection. Meaning: The collection could be implemented internally using an array or an arraylist or even a hashtable. But how we loop through (access the contents of the collection sequentially) without knowing the inner implementation details is the problem.
 
Solution:
  • An abstract Aggregate (Collection) class with an abstract CreateIterator operation.
  • A derived ConcreteAggregate class that creates a class that creates a ConcreteIterator object. 
  • An abstract Iterator class with abstract iteration operations. 
  • A derived ConcreteIterator class that is associated with the ConcreteAggregate object that created it.

The GoF Class structure Diagram

This pattern in so common in .NET it has built-in support from the framework. We can directly map these to elements in System.Collections namespace in .NET.

 Aggregate (AbstractAggregate) –> IEnumerable interface
 CreateIterator method –> CreateEnumerator method
 Iterator (AbstractIterator) –> IEnumerator interface
 First method –> No equivalent
 Next method –> MoveNext() method
 Current method –> Current property
 No equivalent –> Reset method (resets the iterator prior to the first element in the collection)

In fact .NET Framework goes to the extent by adding support for this pattern in the languages VB.NET and C#. For collections which implement IEnumerable they support foreach statement, which is a natural way for the clients to access the collections sequentially.

Advantages:
A generic solution which is implementation agnostic

 

Example implementation:
Many times, the standard collection classes fail to meet our specific needs. In the real world, our programs require custom collection classes that describe entities like automobiles or employees, so supporting enumeration for these classes becomes crucial.

IEnumerable
The IEnumerable interface defines a single GetEnumerator method. As you’ve probably guessed, the purpose of this method is to expose an enumerator that supports simple iteration over a collection of elements. The consumer of a class that implements IEnumerable needs to know very little about the implementation details or private data structures managing the collection of elements. The data structure could be a simple array of integers, a stack of strings, or other custom-built objects. All the consumer needs to know is the data type, so that it can use the foreach statement to iterate over each element in the collection:

foreach (int i in someIntArray) {
  // do something meaningful
}
We want that same sort of behavior in our Products class. That way, the client can enjoy the benefits of iterating with the simple foreach statement, without worrying about the implementation details behind the scenes. Three required class members support foreach: a Current property, and the Reset and MoveNext methods. These three members are defined by IEnumerator. The IEnumerable interface must return an instance of IEnumerator to the caller through its GetEnumerator method. But before we get to the actual interface implementation details, let’s implement the bare bones Products class. Our Products class has an inline Product class that defines an element within the collection. To keep things simple, the Product has a single Name property of type string. Let’s also use a private ArrayList within the Products class to maintain the collection:

public class Products : IEnumerable {

  private ArrayList productList = new ArrayList();

  public Products() {
    // default constructor
  }

  public Product this[int index] {
    get {
      return((Product)productList[index]);
    }
    set {
      productList[index] = value;
    }
  }

  public void Add(Product product) {
    productList.Add(product);
  }

  public int Count {
    get {
      return productList.Count;
    }
  }

  public class Product {

    private string productName;

    public Product(string Name) {
      productName = Name;
    }

    public string Name {
      get {
        return productName;
      }
      set {
        productName = value;
      }
    }
  }
}

As you can see, our Products class contains a single indexer, a Count property, and an Add method to enable the caller to add new elements to the productList ArrayList. The only thing missing is the IEnumerable.GetEnumerator method that is responsible for returning an IEnumerator to the caller. So we have to do two things: build another class that implements IEnumerator, and then implement GetEnumerator within Products to return an IEnumerator instance when the method is called.

IEnumerator
Let’s start by coding the class that implements IEnumerator. As I mentioned earlier, IEnumerator has three members: a property called Current and two methods called MoveNext and Reset. These three, taken together, support the foreach statement. Let’s call the new class that implements these interface members ProductEnumerator, and add it inline within the Products class:

public class ProductEnumerator : IEnumerator {

  private int idx = -1;
  private Products products;

  public ProductEnumerator(Products products) {
    this.products = products;
  }

  public void Reset() {
    idx = -1;
  }

  public object Current {
    get {
      if (idx > -1)
        return products[idx];
      else
        return -1;
    }
  }

  public bool MoveNext() {
    idx++;
    if (idx < products.Count)
      return true;
    else
      return false;
  }
}

This is pretty straightforward. We have an int idx that keeps track of the position in the productList ArrayList. Since the array is zero-based, Reset sets idx to -1 so that it is initialized to a position just before the first element in productList. A call to MoveNext first increments the index to the next element in the collection, and then returns true if it still points to a valid element, or false if it is out of bounds. Finally, a call to Current returns the Product object to which idx points. Now that we’ve implemented IEnumerator, we have something to return when the GetEnumerator method is called. So let’s go ahead and add the GetEnumerator method to our Products class:

public IEnumerator GetEnumerator() {
  return new ProductEnumerator(this);
}

Client-Side
As you can see, the method expects the current Products class to be passed into ProductEnumerator’s constructor, and then the enumerator is returned to the caller. Now we have a fully implemented custom collection class that correctly implements IEnumerable and returns an instance of an inline class that implements IEnumerator.
A consumer of the Products class (for instance, an ASP.NET web page) can build up a collection of Product objects and bind that collection to a list control in just two steps:

Products.Product p1 = new Products.Product("Ikura");
Products.Product p2 = new Products.Product("Chocolade");
Products.Product p3 = new Products.Product("Tofu");
Products.Product p4 = new Products.Product("Konbu");
Products products = new Products();
products.Add(p1);
products.Add(p2);
products.Add(p3);
products.Add(p4);

Repeater1.DataSource = products;
Repeater1.DataBind();

Or, if the caller needs to iterate over each Product object one at a time, it can do so in the usual way with the foreach syntax or by specifically iterating over the IEnumerator instance returned by a call to GetEnumerator:

IEnumerator productEnumerator = products.GetEnumerator();

while (productEnumerator.MoveNext()) {
  Products.Product p = (Products.Product)productEnumerator.Current;
  DropDownList1.Items.Add(p.Name);
}

Why would you ever want to iterate over an IEnumerator instance this way, when you can just use the foreach statement? That’s a fair question. After all, the enumerator returned by a call to IEnumerator.GetEnumerator supports simple forward-only, read-only iteration. So retrieving and enumerating an IEnumerator amounts to the same thing as using the foreach statement.

Note: In reality you need not sweat this much for an ArrayList backed collection implementation, CollectionBase implements IEnumerable too. If you need to use any other backing store than an ArrayList go for a direct IEnumerable implementation. So just derive from CollectionBase. These are the possible reasons for which you’ll directly implement IEnumerable directly.

1. Your collection classes are mandated to inherit from some other class other than CollectionBase
2. You need to return a custom Enumerator which supports scrolling back wards and other fancy features like MovePrevious, MoveLast etc.
3. You need to store the collection items in a structure other than array list. Say I am implementing a Linked List and don’t want to use the ArrayList as a backing store. 

Composite Pattern

November 30, 2005 1 comment

Composite Pattern

Problem:

You are modeling a shipment sent from a Warehouse to a retail Store. The shipments usually are contained in pallets (think of pallet as a container in which products are shipped). A pallet can contain other pallets or individual products. Assume you need to get the total number of products or the total value of products. You want to represent part (product) – whole (pallet) hierarchies of objects. You want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly.

 

Solution:

The composite pattern comes to the rescue. We’ll model something like this:

 

public class ShipmentItem

{

            public virtual int GetNumberOfItems()

            {

                        return 1;

            }

 

            public abstract decimal GetCost();

           

            public virtual void AddShipmentItem(ShipmentItem item)

            {

                        throw new NotSupportedException();

            }

            public virtual void RemoveShipmentItem(int psoition)

            {

                        throw new NotSupportedException();

            }

            public virtual ShipmentItem GetItem(int position)

            {

                        throw new NotSupportedException();

            }         

}

 

public class Pallet : ShipmentItem

{

            private ArrayList shipmentItems;

 

            public Pallet()

            {

                        shipmentItems = new ArryaList();

            }

 

            public override int GetNumberOfItems()

            {

                        int numberOfItems = 0;

                        foreach(ShipmentItem item in shipmentItems)

                        {

                                    numberOfItems += item.GetNumberOfItems();

                        }

                        return numberOfItems;

            }

 

            public override decimal GetCost()

            {

                        decimal  totalCost = 0D;

                        foreach(ShipmentItem item in shipmentItems)

                        {

                                    totalCost += item.GetCost();

                        }

                        return totalCost;

            }

           

            public override void AddShipmentItem(ShipmentItem item)

            {

                        shipmentItems.Add(item);

            }

            public override void RemoveShipmentItem(int psoition)

            {

                        shipmentItems.Remove(item);

            }

            public override ShipmentItem GetItem(int position)

            {

                        return (ShipmentItem)shipmentItems[position];

            }

           

}

 

public class Product : ShipmentItem

{

            private string productCode;

 

            public Product(string UPC)

            {

                        this.productCode = UPC;

            }

           

            public override decimal GetCost()

            {

                        // Retrieve and return the product cost from a datastore based on the product code.

            }

 

            public readonly string UPC

            {

                        get

                        {

                                    return productCode;

                        }

            }         

}

 

public class OrderShipment

{

            private ArryaList items;

 

            public void LoadShipmentDetails(string xml)

            {

                        // Fill the shipment details

            }

 

            public decimal GetShipmentValue()

            {

                        decimal  totalCost = 0D;

                        foreach(ShipmentItem item in items)

                        {

                                    totalCost += item.GetCost();

                        }

                        return totalCost;

            }

           

            public int GetNumberOfItemsInShipment()

            {                     

                        int numberOfItems = 0;

                        foreach(ShipmentItem item in items)

                        {

                                    numberOfItems += item.GetNumberOfItems();

                        }

                        return numberOfItems;

            }

}

 

The GoF class structure diagram

 

Note: In .NET Framework the Composite can be seen ASP.NET Control tree (the Render method or the visible property etc).

Decorator Pattern

November 29, 2005 2 comments

Decorator

Problem:

Too many classes, explosion of the class model. For example we are modelling a portal in which customers place customized orders for laptops. Standard laptop has certain fixed features on top of it customers can choose additional features like additional RAM, additional serial ports, additional drives like DVD ROM Drive, DVD Writer, CD ROM Drive, CD Writer, Floppy drive, Global Warranty, Wireless Card etc.

 

One way to model this is have a base laptop class and one derived class for each of the additional feature permutation, combination. By following this approach the number of classes in the model are going to explode. This approach works only for smaller number of feature combinations. Other approach is to have all of these properties on the Laptop class and set only those ones which the customer buys. But with this approach we are having almost all of the the features as properties even if the customer has not choosen any of the optional features. Such an approach makes client coding difficult.

 

The problem narrows down to adding responsibility (properties / methods) to a class at runtime (without using reflection).

 

Let’s model for a limited case:

 

public class StandardLapTop

{

            private string description = “Standard Laptop”

            private decimal cost = 40000d;

           

            public string Description

            {

                        get

                        {

                                    return description;

                        }

            }

 

            public decimal Cost

            {

                        get

                        {

                                    return cost;

                        }

            }

}

 

public class LapTopWithDVDROM

{

            private string description = “Laptop with DVD-ROM”

            private decimal cost = 45000d;

            public string Description

            {

                        get

                        {

                                    return description;

                        }

            }

            public decimal Cost

            {

                        get

                        {

                                    return cost;

                        }

            }

}

 

public class LapTopWithCDROM

{

            private string description = “Laptop with CD-ROM”

            private decimal cost = 42000d;

            public string Description

            {

                        get

                        {

                                    return description;

                        }

            }

            public decimal Cost

            {

                        get

                        {

                                    return cost;

                        }

            }

}

 

public class LapTopWithDVDROMAndCDROM

{

            private string description = “Laptop with DVD-ROM & CD-ROM”

            private decimal cost = 47000d;

            public string Description

            {

                        get

                        {

                                    return description;

                        }

            }

            public decimal Cost

            {

                        get

                        {

                                    return cost;

                        }

            }

}

 

In this case we just modelled 2 features DVDROM, CDROM. This requires 3 additional classes. Assume we Wireless Card to this we will have StandardLaptop, LaptopWithDVDROM, LapTopWithCDROM, LaptopWithWirelessCard, LaptopWithDVDROMAndWirelessCard, LapTopWithCDROMAndWirelessCard, LapTopWithCDROMAndDVDROMAndWirelessCard. That’s four more. As the number of features increase this just explodes.

 

The problem here is we have added too much of intelligence to the component deciding a static set of combinations for the client.

 

Solution:

The solution will be instead of having a static set of combinations at the compile-time which is not extensible, let the client decide what combination it wants and deal with it. Now the combination of features decision is a runtime decision taken by the client. The client should be able to deal with the base component transparently irrespective of the added combination of features.

 

Have only individual features in the design time and add them to the component (LaptopBase) at runtime. A decorator based solution would be something like this.

 

public interface ILaptopFeature

{

            string Description

            {

                        get;

            }

            decimal Cost

            {

                        get;

            }

}

 

public class StandardLaptop : ILaptopFeature

{

            private string description = "Standard Laptop";

            private decimal cost = 40000M;

 

            public string Description

            {

                        get

                        {

                                    return description;

                        }

            }

 

            public decimal Cost

            {

                        get

                        {

                                    return cost;

                        }                     

            }

}

 

/// <summary>

/// Decorator

/// </summary>

public abstract class Feature : ILaptopFeature

{

            protected ILaptopFeature feature;

            public Feature(ILaptopFeature feature)

            {

                        this.feature = feature;

            }

            public virtual string Description

            {

                        get

                        {

                                    return feature.Description;

                        }         

            }

            public virtual decimal Cost

            {

                        get

                        {

                                    return feature.Cost;

                        }

            }

}

 

public class CDROM : Feature

{

            private string description = "CD ROM Drive";

            private decimal cost = 2000M;    

            public CDROM(ILaptopFeature feature) : base(feature)

            {

                       

            }

            public override string Description

            {

                        get

                        {

                                    return feature.Description + " " + description;

                        }

            }

            public override decimal Cost

            {

                        get

                        {

                                    return feature.Cost + cost;

                        }

            }

}

 

public class DVDROM : Feature

{

            private string description = "DVD ROM Drive";

            private decimal cost = 5000M;    

            public DVDROM(ILaptopFeature feature): base(feature)

            {

                       

            }

            public override string Description

            {

                        get

                        {

                                    return feature.Description + " " + description;

                        }

            }

            public override decimal Cost

            {

                        get

                        {

                                    return feature.Cost + cost;

                        }

            }

}

 

public class ClientApp

{

            public static void Main(string[] args)

            {

                        ILaptopFeature laptopWithCDROM = new CDROM(new StandardLaptop());

                        Console.WriteLine(laptopWithCDROM.Description + " costs " + laptopWithCDROM.Cost);

           

                        ILaptopFeature laptopWithDVDROM = new DVDROM(new StandardLaptop());

                        Console.WriteLine(laptopWithDVDROM.Description + " costs " + laptopWithDVDROM.Cost);

 

                        ILaptopFeature laptopWithCDAndDVDROM = new CDROM(new DVDROM(new StandardLaptop()));

                        Console.WriteLine(laptopWithCDAndDVDROM.Description + " costs " + laptopWithCDAndDVDROM.Cost);

 

                        Console.ReadLine();

 

            }

}

 

Adding a new feature is just adding one class and not 3 as in the non decorator approach.

 

public class WirelessCard : Feature

{

            private string description = "Wireless Card";

            private decimal cost = 10000M;  

            public WirelessCard(ILaptopFeature feature): base(feature)

            {

                       

            }

            public override string Description

            {

                        get

                        {

                                    return feature.Description + " " + description;

                        }

            }

            public override decimal Cost

            {

                        get

                        {

                                    return feature.Cost + cost;

                        }

            }

}

 

The GoF Class Structure Diagram is as follows:

 

 

Note: In the .NET Framework, Stream class is the base component class which can be decorated by the MemoryStream or CryptoStream.

Strategy Pattern

November 29, 2005 1 comment

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.