Monday, February 9, 2009

Design Patterns: Singleton Facade (with C# .NET Sample)

Facade is an object that provides common access point to the application class library; it is accessible for large set of application objects through well designed API with convenient methods.

When designing a large system with many classes that are spread across many packages it's often make sense to design a facade that is accessible to all application objects and through which application objects from different packages can be accessed.

In client-server applications Remote Facade is used to minimize the number of remote calls; with the Remote Facade pattern client interacts with coarse-grained server object (called Remote Facade) that translates coarse-grained methods onto the underlying fine-grained objects.

This post walks through several implementations of the facade pattern and offers solutions for common dilemmas that raise during the implementation of the facade.

Singleton Facade - Tightly Coupled

The most common facade is a singleton object that acts as the main access point of the application through which the main objects (managers, controllers etc) can be accessed and common operations can be executed. Such facade is often responsible for instantiating and initializing the main objects and getting the application up and running.

The following facade manages three table module objects and one plug-in object, it creates the objects upon initialization (via LoadSystem) and exposes their interfaces to its clients. It also provides function to easily pull out the orders of a given customer from the data source.

image 

image_thumb22  Since the facade is supposed to be accessible to almost every application object - it will be best if it will reside in a common component (dll) that has as few dependencies as possible. However, since the facade object instantiate the types that it's exposes it's due to depend on components from all across the system. 

The problem with this facade is that in order to instantiate and initialize the table modules and the plug-in object its component includes the Markrt.Core and the Market.Plugin components, consequently, the facade users (Client1 and Client2) also indirectly include the latter components which is obviously a problem.

Another problem is that the facade core components (Market.Core and Market.PlugIn) cannot use the facade in order to interact with each other (due to circular reference). For example, CustomerTableModule (from Market.Core) cannot use ReportManager (from Market.PlugIn) through the facade.

image_thumb14  The good thing about the this facade is that it's simple. In small applications its often make sense to keep it simple and live with a little tightly coupled facade, though it can work  only incase the facade has few clients and its underlying objects don't have to interact with each other.

Singleton Facade - Loosely Coupled

In order to solve the dependencies problem of the latter facade we should come out with a loosely coupled facade that doesn't depend on "core" component such as Markrt.Core and Market.Plugin.

The obvious place for such facade is in the Market.Common package that is reachable though all across the system and doesn't dependent on other components.

The problem is that once the facade is moved to the Market.Common package it cannot instantiate the main objects of the system (via LoadSystem) any more, in order to solve this problem we'll change the scope of the MiniMarketFacade internal fields (m_Customers, m_Orders etc) from private to protected, add new class called 'MiniMarketFacadeImp' that inherits from MiniMarketFacade, and move the LoadSystem implementation from MiniMarketFacade to the new MiniMarketFacadeImp class. Now, MiniMarketFacadeImp will instantiate the main objects and populate MiniMarketFacade protected fields.

image

 image_thumb22  Indeed, separating the facade into two classes that reside in different components will make it a little more complex, but large systems cannot afford tightly coupled facade so we really don't have much of a choice.

image_thumb14  Placing the facade in Market.Common turned out to be a great move that certainly worth the effort. The facade clients are not forced to include the core components, they depend only on Market.Common component. The core components (Market.Core and Market.Plugin) can now use the facade in order to interact with each other.