Facade Pattern
Introduction
Developers in .NET sometimes come from scripting language environments that are not strong on Object Oriented Methodologies. OO methodologies like refactoring and using design patterns can be intimidating and the value for the developer is hard to see. What developers new to the OO world, and even more seasoned developers need to understand is that good design is not beyond scope in any project. Good habits simply must be learned that will make the developer a better designer.
In that mind set, I am submitting the first of several "how to" real
world examples, used in my professional life, on how to use patterns in a simple,
easy to follow manner. Many of us have ended up either writing or working on
in-line, scripting based code. Taking some ideologies from refactoring methodology,
this is not necessarily a bad thing. Of course, when you are first writing an
algorithm or a series of logic statements, it seems easier to start with if....then....else
.
But as you continue to expand this code to more complex forms, this model can
quickly become unmanageable. This is where refactoring and design pattern methodology
can play an important and useful part in simplifying, enhancing and making code
more useable (and understandable) to those who practice good OO design.
This article details a real world example of how to use facade patterns to help you deal with a modular code system, such as business layer algorithms, or any code which you wish to extract into it's own assembly/namespace and allow only specific access to from outside the assembly/namespace. The strictest definition of a facade pattern is any code you wish to provide a single access point to, limiting the access points to other classes and parts of code that you do not wish to be accessed outside of the assembly/namespace.
BackGround
I have used facades usually in modular code for either business layers or handy API assemblies. In this example, which is straight from real world code I developed in my professional life, I illustrate how to use a facade pattern to create a piece of modular functional code.
How to use the code
.NET uses the class and method modifier internal
to restrict access
to classes and methods in an assembly to have access only internally
to the assembly/namespace where the class or method exists. Using this class
modifier, we can restrict any and all classes we wish to remain effectively
hidden to code executing outside our module assembly/namespace.
We start off with some functional code that we wish to extract into our module assembly. Keep in mind when designing a modular system, you should decide at the outset which methods and/or classes you wish to give code executing outside the assembly/namespace access to, and which classes you wish to hide.
public class DoSomeWork { public DoSomeWork(WorkerObject workerObject) { //some logical code....... } }
Next we build our basic facade and interface classes, marking method modifiers
we wish to have external access to as public. First we need to build a contract
or interface that allows access to our facade class. The IDoSomeWork
facade will define how code outside the assembly will access and work with your
module code.
NOTE: Notice that no modifier is necessary on the interface method DoSomeWork
.
This is because methods on an interface are always implicitly public to the
interface's level of access.
namespace DoSomeWorkModule { public interface IDoSomeWork { void DoSomeWork(WorkerObject workerObject); } }
Next we build our facade class, DoSomeWorkFacade
, which will contain
the actual functional code, or pointers to other internal
classes
in the assembly, that actually do the work. Notice that on the DoSomeWork
method we add the IDoSomeWork
interface as a map to the method.
This declares that only the interface may access this method.
namespace DoSomeWorkModule { public class DoSomeWorkFacade : IDoSomeWork { public void IDoSomeWork.DoSomeWork(WorkerObject workerObject) { //some logical code....... } } }
To declare for usage, you must do so thus:
IDoSomeWork doSomeWorkFacade = new DoSomeWorkFacade();
doSomeWorkFacade.DoSomeWork(workerObject);
Notice that we called the DoSomeWork
method by instantiating DoSomeWorkFacade
facade and setting its access contract with IDoSomeWork
. Since
we mapped the DoSomeWork
method to the IDoSomeWork
interface, we can only call this method as stated in the interface contract.
We cannot, for example, call any method mapped to the interface thus:
DoSomeWorkFacade doSomeWorkFacade = new DoSomeWorkFacade();
doSomeWorkFacade.DoSomeWork(workerObject); //throws a compile time error, no such accessible method
Now that we have set up our facade classes, we can deal with some of the other
classes, related to and supporting our facade. First lets deal with the class
passed into the DoSomeWork
method, WorkerObject
. This
class is a simple data object, and is part of the namespace for the module DoSomeWorkModule
.
It's modifiers are public even though it is contained in our module, because
we want executing code outside the assembly to have access to it. The executing
code can then pass this object in as a parameter to our facade.
namespace DoSomeWorkModule { public class WorkerObject { private object _obj1; public object Object1 { get{return _obj1;} set{_obj1 = value; } } }
We will also have some other classes, perhaps based on different patterns,
that exist inside the assembly, that have internal
access modifiers.
These classes are support classes that help the code internal to the facade
do it's work. Here we have as an example a class loosely based on the mediator
pattern named DoSomeMediation
. DoSomeMediation
registers
a series of WorkerObjects
within, and contains a method to send
messages to all WorkerObjects
it contains, in effect, mediating
between the registered objects. (More on the mediator pattern, will be
covered in a later article). The thing to notice here is that DoSomeMediation
is marked with the modifier internal
. This prevents access of the
class outside of the namespace, which will be called from the DoSomeWork
method on the DoSomeWorkFacade
.
namespace DoSomeWorkModule { internal class DoSomeMediation { internal void Register(WorkerObject workerObject) { //registers work order objects within the class } internal void Send() { //sends a message to all registered work order objects } } }
Expanding the Example
A reader posed a good question: how do you keep users from accessing the constructor
of the implementation class? The answer is by creating the interface contract
for the class via a factory. You would in this case mark the DoSomeWorkFacade
facade class as internal, and have the factory build the implementation. Of
course your factory create method has to be externally accessible, but the DoSomeWorkFacade
class can now be marked internal
.
namespace DoSomeWorkModule { internal class DoSomeWorkFacade : IDoSomeWork { internal void IDoSomeWork.DoSomeWork(WorkerObject workerObject) { //some logical code....... } } public class DoSomeWorkFactory { public static IDoSomeWork GetFacade() { IDoSomeWork doSomeWorkFacade = new DoSomeWorkFacade(); return doSomeWorkFacade; } } }
Points of Interest
This is the second installment in the series I am writing on real world design patterns. All examples and the bulk of this article are taken from my professional experience as an architect. The examples given are templates only, and the designer must keep in mind that they are the ones who must decide where different patterns, if any, may be best used in their code.
Deciding to perform a refactoring effort from existing code to a pattern must be weighed on the necessity and need of the code itself. Patterns are only design templates, helpers to accommodate better overall design. I might stress that making the effort to use patterns will strengthen your overall design ability, but like your basic coding skills, it is something learned and cultivated.
If this or any other in this series on design patterns is helpful or you have questions or comments please e-mail me at chris.lasater@gmail.com.
History
This is the first revision and is the second installment in a series.
Related Articles
Other articles in this series include: