Design Patterns 101 - The Abstract Factory Pattern

by Edward 31 January 2010 18:41

In my second article on design patterns, I am going to give you a quick overview of the "Abstract Factory pattern". Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

The Abstract Factory pattern is one level of abstraction higher than the factory pattern. One of the nice things about abstraction is that it lets you "take care" of the bigger picture and you only have to worry about the "details" later. The great advantage is that you are able to rely upon some other class to fill in the details for you.

You can use this pattern when you want to return one of several related classes of objects, each of which can return several different objects on request. In other words, the Abstract Factory is a factory object that returns one of several factories.

The code below demonstrates the Abstract Factory pattern creating parallel hierarchies of objects. Object creation has been abstracted and there is no need for hard-coded class names in the client code.

 

   1:  // Abstract Factory pattern - Structural example
   2:   
   3:  using System;
   4:   
   5:  namespace MyApp.AbstractFactory.Structural 
   6:  {
   7:      /// <summary>
   8:      /// MainApp startup class for Structural
   9:      /// Abstract Factory Design Pattern.
  10:      /// </summary>
  11:      internal class MainApp
  12:      {
  13:          /// <summary>
  14:          /// Entry point into console application.
  15:          /// </summary>
  16:          public static void Main()
  17:          {
  18:              // Abstract factory #1
  19:              AbstractFactory factory1 = new ConcreteFactory1();
  20:              Client client1 = new Client(factory1);
  21:              client1.Run();
  22:   
  23:              // Abstract factory #2
  24:              AbstractFactory factory2 = new ConcreteFactory2();
  25:              Client client2 = new Client(factory2);
  26:              client2.Run();
  27:   
  28:   
  29:              // Wait for user input
  30:              Console.ReadKey();
  31:          }
  32:      }
  33:   
  34:      /// <summary>
  35:      /// The 'AbstractFactory' abstract class
  36:      /// </summary>
  37:      internal abstract class AbstractFactory
  38:      {
  39:          public abstract AbstractProductA CreateProductA();
  40:          public abstract AbstractProductB CreateProductB();
  41:      }
  42:   
  43:      /// <summary>
  44:      /// The 'ConcreteFactory1' class
  45:      /// </summary>
  46:      internal class ConcreteFactory1 : AbstractFactory
  47:      {
  48:          public override AbstractProductA CreateProductA()
  49:          {
  50:              return new ProductA1();
  51:          }
  52:   
  53:          public override AbstractProductB CreateProductB()
  54:          {
  55:              return new ProductB1();
  56:          }
  57:      }
  58:   
  59:      /// <summary>
  60:      /// The 'ConcreteFactory2' class
  61:      /// </summary>
  62:      internal class ConcreteFactory2 : AbstractFactory
  63:      {
  64:          public override AbstractProductA CreateProductA()
  65:          {
  66:              return new ProductA2();
  67:          }
  68:   
  69:          public override AbstractProductB CreateProductB()
  70:          {
  71:              return new ProductB2();
  72:          }
  73:      }
  74:   
  75:      /// <summary>
  76:      /// The 'AbstractProductA' abstract class
  77:      /// </summary>
  78:      internal abstract class AbstractProductA
  79:      {
  80:      }
  81:   
  82:      /// <summary>
  83:      /// The 'AbstractProductB' abstract class
  84:      /// </summary>
  85:      internal abstract class AbstractProductB
  86:      {
  87:          public abstract void Interact(AbstractProductA a);
  88:      }
  89:   
  90:      /// <summary>
  91:      /// The 'ProductA1' class
  92:      /// </summary>
  93:      internal class ProductA1 : AbstractProductA
  94:      {
  95:      }
  96:   
  97:      /// <summary>
  98:      /// The 'ProductB1' class
  99:      /// </summary>
 100:      internal class ProductB1 : AbstractProductB
 101:      {
 102:          public override void Interact(AbstractProductA a)
 103:          {
 104:              Console.WriteLine(this.GetType().Name +
 105:                                " interacts with " + a.GetType().Name);
 106:          }
 107:      }
 108:   
 109:      /// <summary>
 110:      /// The 'ProductA2' class
 111:      /// </summary>
 112:      internal class ProductA2 : AbstractProductA
 113:      {
 114:      }
 115:   
 116:      /// <summary>
 117:      /// The 'ProductB2' class
 118:      /// </summary>
 119:      internal class ProductB2 : AbstractProductB
 120:      {
 121:          public override void Interact(AbstractProductA a)
 122:          {
 123:              Console.WriteLine(this.GetType().Name +
 124:                                " interacts with " + a.GetType().Name);
 125:          }
 126:      }
 127:   
 128:      /// <summary>
 129:      /// The 'Client' class. Interaction environment for the products.
 130:      /// </summary>
 131:      internal class Client
 132:      {
 133:          private AbstractProductA _abstractProductA;
 134:          private AbstractProductB _abstractProductB;
 135:          
 136:          // Constructor
 137:   
 138:          public Client(AbstractFactory factory)
 139:          {
 140:              _abstractProductB = factory.CreateProductB();
 141:              _abstractProductA = factory.CreateProductA();
 142:          }
 143:          
 144:          public void Run()
 145:          {
 146:              _abstractProductB.Interact(_abstractProductA);
 147:          }
 148:      }
 149:  }

Output:

ProductB1 interacts with ProductA1
ProductB2 interacts with ProductA2


The Usage of this pattern makes it possible to interchange concrete classes without changing the code that uses them, even at runtime! However, employment of this pattern, as with similar design patterns, may result in unnecessary complexity and extra work in the initial writing of code. Used correctly the "extra work" pays off in the second instance of using the Factory.

Tags: , ,

ASP.NET | Development Resources | Social Media

Design Patterns 101 - The Singleton Pattern

by Edward 29 January 2010 18:53

You probably heard of it, you probably don't even know that you are implementing it, but you need it on your resume! Once you start to use design patterns you will find that your code structure is improving. This is a "101" article about the simplest pattern - the Singleton pattern.

The purpose of this pattern is to ensure that a class has only one instance, and provide a global point of access to it. Any class in your application that has access to its namespace doesn't have to create or initialize the singleton. The caller can access properties and methods through the singleton's instance property. The singleton will retain state across calls.

   1:  // Singleton pattern - Structural example
   2:   
   3:  using System; 
   4:   
   5:  namespace MyApp.Singleton.Structural
   6:  {
   7:   
   8:    /// <summary>
   9:    /// MainApp startup class for Structural
  10:    /// Singleton Design Pattern.
  11:    /// </summary>
  12:   
  13:    class MainApp
  14:    {
  15:      /// <summary>
  16:      /// Entry point into console application.
  17:      /// </summary>
  18:   
  19:      static void Main()
  20:      {
  21:        // Constructor is protected -- cannot use new
  22:        Singleton s1 = Singleton.Instance();
  23:        Singleton s2 = Singleton.Instance(); 
  24:   
  25:        // Test for same instance
  26:        if (s1 == s2)
  27:        {
  28:          Console.WriteLine("Objects are the same instance");
  29:        }
  30:   
  31:        // Wait for user
  32:        Console.ReadKey();
  33:      }
  34:    }
  35:   
  36:    /// <summary>
  37:    /// The 'Singleton' class
  38:    /// </summary>
  39:   
  40:    class Singleton
  41:    {
  42:   
  43:      private static Singleton _instance;
  44:   
  45:      // Constructor is 'protected'
  46:      protected Singleton()
  47:      {
  48:      }
  49:   
  50:      public static Singleton Instance()
  51:      {
  52:        // Uses lazy initialization.
  53:        // Note: this is not thread safe.
  54:        if (_instance == null)
  55:        {
  56:          _instance = new Singleton();
  57:        }
  58:   
  59:   
  60:        return _instance;
  61:      }
  62:    }
  63:  }


Output:

Objects are the same instance

Note: The singleton pattern must be carefully constructed in multi-threaded applications. If two threads are to execute the creation method at the same time when a singleton does not yet exist, they both must check for an instance of the singleton and then only one should create the new one.

Tags: , , ,

ASP.NET | Development Resources | Social Media

Download Updated VS2010 and .NET 4 Training Kit

by Edward 12 January 2010 14:41

The updated VS2010 and .NET 4 Training Kit includes presentations, hands-on labs, and demos. Some of the features include:

  • C# 4.0
  • Visual Basic 10
  • F#
  • Parallel Extensions
  • Windows Communication Foundation
  • Windows Workflow
  • Windows Presentation Foundation
  • ASP.NET 4
  • Windows 7
  • Entity Framework
  • ADO.NET Data Services
  • Managed Extensibility Framework
  • Visual Studio Team System

You can download the training kit from the Microsoft website.

Come next month, Microsoft will offer testers yet another development milestone release of both Visual Studio 2010 and .NET Framework 4.

This version of the Training Kit works with Visual Studio 2010 Beta 2 and .NET Framework 4 Beta 2.

Tags: , , , ,

ASP.NET | Development Resources | Technology

About DasCode.Net

I'm a ASP.NET web developer and code enthusiast. Blogging about everything .Net related.

Code... that's .net

Month List