Back again with design patterns, defining them briefly and the design principles they are based on, and providing several very good (almost) real-world C# examples that are available on the Internet.  In this series we have the factory patterns and the singleton pattern and their several different implementations.

Design Pattern #4: Factory Method Pattern

  • Defines an interface for creating an object but lets subclasses decide which class to instantiate.  It lets a class defer instantiation to the subclasses.
  • Design Principle:
    • Design Principle #6 :  Depend on abstraction.  Do not depend on concrete classes.
  • C# Examples:
    • Example using multiple vehicle factories where each vehicle factory produces only one type of vehicle.

      Product Vehicle
      ConcreteProduct Bike, Car, Bus
      Creator Factory; with abstract method GetVehicle()
      ConcreteCreator TwoWheeler, CompactFourWheeler, FourWheeler
    • An online bookstore application using multiple distributors to send books to its customers.  This example uses the parameterized factory implementation or the procedural solution/basic noob implementation, wherein the bookstore factory receives the customer location to determine which distributor to choose from.

      Product IDistributor
      ConcreteProduct EastCoastDistributor, MidwestDistributor, WestCoastDistributor
      Creator IBookStore; with abstract method GetDistributor()
      ConcreteCreator BookStoreA
    • A lodging inquiry system wherein a customer can get details of different types of available rooms.  This example also shows the registration with reflection implementation, the self registration without reflection implementation and the self registration with reflection implementation.  It is actually using a factory pattern, a pattern that is the basis for the factory method pattern and the abstract factory pattern. The only difference between the factory pattern and the factory method pattern is in the creator. The factory method pattern requires an abstract class which defines the interface for several factories, thus abstracting the client from both the type of product and type of factory used to create the product.

      Product IRoomType
      ConcreteProduct ACRoom, DeluxeRoom, NonACRoom
      Creator -
      ConcreteCreator RoomFactory; concrete class with concrete method GetRoomType()

Design Pattern #5: Abstract Factory Pattern

  • Provides an interface for creating families of related or dependent objects without specifying their concrete classes.
  • Design Principle:
    • Same as the factory method pattern, it follows the Design Principle #6.
  • C# Examples:
    • A drawing and printing machine that can process low and high resolution.  This can be extended to process medium resolution by creating a medium resolution factory that provides the medium resolution display and print drivers.

      AbstractFactory ResFactory; with abstract methods getDispDrvr() and getPrtDrvr()
      ConcreteFactory LowResFact, HighResFact
      AbstractProduct DisplayDriver, PrintDriver
      ConcreteProduct LowDisplayDriver, HighDisplayDriver, LowPrintDriver, HighPrintDriver
      Client ApControl
    • An audio/video device object providing access to it’s audio and video properties.  Again this can be extended to include Bluray by creating a Bluray object that exposes Bluray audio and video objects.

      AbstractFactory IAVDevice; with abstract methods GetAudio() and GetVideo()
      ConcreteFactory CCd, CDvd
      AbstractProduct IAudio, IVideo
      ConcreteProduct CCdAudio, CDvdAudio, CCdVideo, CDvdVideo
      Client CAVMaker
    • An example using employee and customer factories that provides personal information.  This example shows the dependency injection implementation and the inversion of control container implementation.  These types of implementations, factory pattern, dependency injection, and inversion of control container, are all techniques to implement inversion of control, a programming technique in which object coupling is bound at run time and is typically not known at compile time.  I will talk more about inversion of control on a separate post, as this I think, is a hot topic too in the object oriented programming world.

      AbstractFactory IPersonAbstractFactory
      ConcreteFactory EmployeeFactory, CustomerFactory
      AbstractProduct IPerson
      ConcreteProduct Employee, Customer
      Client MySample

Design Pattern #6: Singleton Pattern

  • Ensures a class only has one instance and provides a global point of access to it
  • C# Examples:
    • Singleton implementations from MSDN.  It shows 3 implementations: the basic implementation, the static initialization implementation, and the multithreaded or double-check locking implementation.
    • Singleton implementations from the book C# In Depth.  It shows 6 implementations:
      • basic implementation that is not thread-safe
      • simple thread-safe implementation using a lock
      • attempted thread-safe using double-check locking implementation
      • static initialization implementation that is thread-safe without using locks but not quite as lazy
      • full lazy static initialization implementation
          public sealed class Singleton  
          {  
          private Singleton()  
          {  
          }  
                      
          public static Singleton Instance { get { return Nested.instance; } }  
                          
          private class Nested  
          {  
              // Explicit static constructor to tell C# compiler  
              // not to mark type as beforefieldinit  
              static Nested()  
              {  
              }  
                  
              internal static readonly Singleton instance = new Singleton();  
          }  
          }
        
      • C# 4.0’s Lazy static initialization implementation
          public sealed class Singleton  
          {  
          private static readonly Lazy<Singleton> lazy =  
              new Lazy<Singleton>(() => new Singleton());  
                      
          public static Singleton Instance { get { return lazy.Value; } }  
                      
          private Singleton()  
          {  
          }  
          }
        
  • This is the second in the Design Patterns series.  The first one is Design Patterns: Strategy, Observer, and Decorator.