ghytred.com


NewsLook for Outlook

Patterns and OO
AdaptorAndFacade
The Web Site you seek
Cannot be located, so
Waste your time here

Contents

Adaptor Pattern

The purpose of Adaptor is to fit a class with one interface into a system, which expects a different interface. As an example, consider an AddIn to the VB6 IDE. This is a DLL, which exposes a given Interface. We wish to use that as an AddIn to VS.NET � which requires that it expose a different interface. The solution is to provide a class, which exposes the Interface required by VS.NET and delegates calls to an internally created instance of the original VB6 AddIn.

In general, when integrating a pre-existing object into a pre-existing system it is unlikely that the interfaces exposed by the object are the interface(s) required by the system. In this case, you use an Adaptor pattern.

The GoF book has two ways of implementing this pattern � what it calls �Class Adaptor� and �Instance Adaptor�. The Class Adaptor requires multiple inheritance and so I�ll leave it out. The Instance Adaptor has an internal instance of the object you want to adapt, exposes the interface required by the system, which wants to use the object, and translates between the two. Adaptor could also be called �Intelligent Wrapper�.

One example of the Adaptor pattern is the .NET DataAdaptor. This adapts a DataReader and allows the easy filling and updating of DataSets. Filling a DataSet does not extend the functionality of DataReader � it simplifies its interface (in a way that Mediator might). Updating via a DataAdaptor extends the functionality of DataReader; it can do this only by knowing the �client� � the DataSet � it is extending it for.

Adaptor, then, takes an existing interface and adapts it for use in a specific context. In this new context, the existing interface is either inappropriate or inaccessible, and the pattern makes it available in an appropriate form to consumers in the new context.

Facade

The purpose of a Facade is to limit interface of a sub-system to a single interface, which translates calls to it into possibly multiple calls to objects within the sub-system. This is usually done to protect a consumer from a complex or large set of objects, which are easy to misuse, and to protect the sub-system from that misuse.

Facades can also be used to concentrate �orthogonal� functionality, for example security checks. If all calls to a sub-system go through one facade then security checks can be concentrated in the facade.

The larger and more complex the sub-system is, the more its clients depend on it being stable. Using a facade allows the actual implementation of the functionality to change without necessarily affecting the interface to it, protecting the clients. This reduces the coupling of the client to the sub-system and is thus a Good Thing�.

Facades can become all-knowing God-objects. This is not a Good Thing� and must be guarded against. Perhaps the easiest way to avoid this is to design and write the Facade object only when the sub-system is fully written and unit tested. Sadly, I have seen very few facades, which did not end up with considerable knowledge and intelligence about the sub-system they are meant to be merely a doorway into.

The following is an example of a facade to a memory-management sub-system.

public class MemoryFacade { public MemoryFacade() {} public int Free { get { return MemorySingleton.Instance.Free; } } public int Used(int user) { return MemorySingleton.Instance.UsedBy(user); } public void AssignRange(int length, int User) { if (User <= 0) throw new Exception("Zero user"); if (User >= 10) throw new Exception("user out of range"); if (length == 0) throw new Exception("0 range? C'mon!"); MemoryManager.Assign(length, User); return; } public byte[] Read(int user, int start, int length) { if (user <= 0) throw new Exception("Zero user"); if (user >= 10) throw new Exception("user out of range"); if (length == 0) throw new Exception("0 range? C'mon!"); return MemoryManager.Read(user, start, length); } public void Write(int user, int start, byte[] content) { if (user <= 0) throw new Exception("Zero user"); if (user >= 10) throw new Exception("user out of range"); MemoryManager.Write(user, start, content); } public void Dispose() { MemorySingleton.Clear(); } }

Return to top