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.  

Monday, December 15, 2008

Design Patterns: Visitor vs. Strategy (with C# .NET Sample)

Both visitor and strategy design patterns offer a way of separating an algorithm from an object, in this post we'll review the implementation of the patterns in a simple car wash application and try to figure out in which cases each pattern should be applied.  

Basic Object Model

The Car object is composed out of wheel, engine and body, each implements ICarElement.

image

As for now, we know that the application should support 2 kind of operations:

1. washing the car by steam.

2. washing by water.

however, the design should support more operations that will be added in the future.

Straight forward Implementation

With the most simple and straight forward approach the operations are implemented in the car elements body.

image

image

image The good thing is that it's all right in front of you, if you want to browse through the operations you don't have to look around, you go directly to the basic object model.

image The problem with the straight forward approach is that the basic object model has to be changed with each new operation that will be required in the future, as for each new operation all the elements of the car (wheel, engine and body) have to be added with an extra function. Also, the tight coupling between the basic object model and the operation makes it harder to replace operation implementation of the fly.

Strategy

With the Strategy approach there's a separate strategy object for each one of the operations. image

The element is assigned with the proper strategy, and when it is requested to do a wash - it delegates the request to the strategy that performs the wash. 

 image

imageWith this approach the basic object model is not required to change with every new operation, and operation can be gracefully replaced on the fly.

image The problem is that there are too many strategy objects, in order to replace a washing technic from 'by water' to 'by  stream' - three strategies have to be replaced. Also, with each new operation three strategies (one for each element) have to be added to the application.

Visitor

With the Visitor approach there's one visitor object for each kind of operation ('wash by water', 'wash by steam'); the visitor object contains operation implementation for all the elements of the car (wheel, engine and body). For example, the 'stream wash' operation kind has SteamWashVisitor that contains steam washing implementation for all the elements of the car.

image

When the element is requested to do a wash - it calls the appropriate method on the visitor. 

image

imageWith this approach the basic object model is not required to changed with every new operation, and operation implementations for all the elements are bundled in one Visitor that can be replaced as a whole. For example, in order to replace a washing technic from 'by water' to 'by  stream' - all we have to do is to replace the Visitor object from WaterWashVisitor to SteamWashVisitor.

image When ever the basic object model changes all the Visitors have to be changed as well, for example, if a new 'Door' object is added to the car - all the visitors have to be added with an extra 'VisitDoor' method. This is why the Visitor pattern is applicable only if the basic object model doesn't tend to change.

Summery

In most cases the operations are implemented in the body of the object on which they operate.

Often, operations are implemented in an external package or have to be replaced of the fly according to application rules, for this strategies can be used to allow external operations injection and graceful operations replacement.

In other cases (not that often) the same kind of operation has to be executed on several elements (that usually share interface) in the object model, and there's a need to easily replace the entire set of operations on the fly. Only in condition that the object model is steady and doesn't tend to change - visitors can be used to group set of operations in one object that can be  easily replaced.