Design Patterns: Factory Method, Abstract Factory, and Singleton

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:
    • 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<T> 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.

Design Patterns: Strategy, Observer, and Decorator

Here and in the next posts, I will talk about design patterns, it’s definition, the guiding design principles they embody, and their C# examples.  But before you dive into design patterns, here is a refresher on four OO basics.

 

Design Pattern #1: Strategy Pattern

  • Defines a family of algorigthms, encapsulates each one, and makes them interchangeable.  It lets the algorithm vary independently from clients that use it.
  • Design Principles:
    • Design Principle #1 : Separate code that change from code that stays the same
    • Design Principle #2 : Program to an interface and not to an implementation
    • Design Principle #3 : Favor composition (HAS-A) over inheritance (IS-A)
      • Note: To implement composition, a class will have an interface type reference to a concrete implementation that is usually initialized during the class constructor

 

Design Pattern #2: Observer Pattern

  • Defines a one-to-many dependency between objects so that  when one object changes state, all of its dependents are notified and  updated automatically.  A good example is a newspaper publisher and its  subscribers.
  • Design Principles:
    • Design Principle #4 : Strive for loosely coupled designs between objects that interact

 

Design Pattern #3: Decorator Pattern

  • Attaches additional responsibilities to an object dynamically.  Decorators provide a flexible alternative to sub-classing for extending functionality.  It does this by using composition and delegation.  Decorator classes have same types as the components they decorate, either through inheritance or interface implementation.  They add behavior by adding new functionality before and/or after method calls to the component.
  • Design Principles:
    • Design Principle #5 : Classes should be open for extension but closed for modification

Design Patterns: The Four OO Basics

Before going into design patterns, one must need to know the four OO basics:

  • Abstraction is showing only the necessary details to the outside world. It is the abstract form of anything. It is implemented using interface and abstract class.
  • Encapsulation is hiding the details from the outside world. It is the opposite of abstraction. It is implemented using private and protected access modifiers inside a class.
  • Inheritance is a way for an entity to inherit the characteristics of another entity, thus establishing a parent-child relationship, or in a more technical OO term, an IS-A relationship. It is implemented using base and derived classes.

Design Patterns: Fundamentals

Fundamental design patterns are divided into 3 categories:

EDIT: The above patterns are called the 23 Gang of Four (GoF) patterns.  More information can be found from this link.  The site provides a description, a UML class diagram and C# code as well.

Design Patterns: Mediator, Adapter, Proxy, and Observer Patterns

Mediator Pattern

This pattern mediates between objects.  If you have several objects that need to interact with each other and you find yourself having common attributes and behaviors on each of your objects, you can use the mediator pattern.  You create a mediator object that encapsulates these common attributes and behaviors and if you need to change the way your objects interact with each other, you only have to change the mediator object.

Adapter Pattern

This pattern adapts an object to be usable by another object.  If you have an object A that is being used by another object B and later you upgraded object B thereby making object A unusable, you can use the adapter pattern.  You create an adapter object that fits between object A and object B and this will allow object A to remain usable by object B.

Proxy Pattern

This pattern allows a local code to work with a remote object all the while thinking it’s a local object.  If you have a code where you use a local object and later found yourself needing to use a remote object and you don’t want your local code to know it’s using a remote object, you can use the proxy pattern.  You create a proxy object that your local code will use and this proxy object will then connect to the remote object.

Observer Pattern

This pattern is about objects that are observing for a particular event to occur and waiting for the subject that they registered to to notify them when the event has occurred.  In .NET, this pattern is implemented as events or event handlers.