What it is the wrapper/facade pattern?
A wrapper, or facade, is when you create a new class, in order to hide how another class (or group of classes) works.
If you’d like to see this as a video, watch it here:
Why would you use a wrapper/facade?
There are two main reasons why you would use a wrapper.
The first is when you have a class, or a group of classes, that are complex to work with. For example, if you want to send an e-mail. In order to send an e-mail from a C# program, you need to create an e-mail message object, possibly create multiple objects for the e-mail addresses, and create an e-mail server object. Then, you can finally send out the e-mail. You also need to remember to include two “using” statements for namespaces that are rarely used.
That’s a lot of objects to create, in a specific order, just to send out an e-mail. It would be nice if you could create a single, simpler object that will hide all that complexity.
The second reason, which is less common, is to hide the implementation of third-party libraries – especially if they might change over time. Many libraries are updated at least once a year. And, occasionally, an update has a change that breaks your existing code.
If you have wrapper classes, that don’t do anything other than inherit from the library’s classes, you might be able to make one change in the wrapper class, in order to make the updated library work the way you want it to work.
Code Samples
For this demonstration, I’ll create a wrapper class in C# that sends an e-mail.
Simple version, without a wrapper/facade
If you’re sending a simple e-mail – only one “to” recipient – the code can be fairly simple, like this:
using System.Net; using System.Net.Mail; namespace DesignPatternDemos.Facade { public class MyClassForFacade { public void DoSomethingSimple() { // Pretend there is business-logic here // Send an e-mail - simple version, with one "to" address MailMessage simpleEmail = new MailMessage("from@test.com", "to@test.com", "Email subject here", "Email body here"); // Set up the mail server SmtpClient smtpClient = new SmtpClient("mailservername"); smtpClient.Credentials = CredentialCache.DefaultNetworkCredentials; smtpClient.Timeout = 100; // Send the email smtpClient.Send(simpleEmail); } } }
After you create the MailMessage, there is a little configuration that needs to be done for the mail server (SmtpClient). You also need to remember to include “using” statements for “System.Net” and “System.Net.Mail”.
More complex version, without a wrapper/facade
If you want to send an e-mail to multiple recipients (or CC and BCC recipients), the code gets noticeably longer. Plus, you need to use three different types of objects – MailMessage, several MailAddress objects, and the SmtpClient. It takes 36 lines of code to send out this sample e-mail.
using System.Net; using System.Net.Mail; namespace DesignPatternDemos.Facade { public class MyClassForFacade { public void DoSomethingComplex() { // Pretend there is business-logic here // Send an e-mail - complex version, with multiple "to", "cc", and "bcc" addresses. MailMessage email = new MailMessage(); MailAddress fromAddress = new MailAddress("from@test.com"); email.From = fromAddress; MailAddress toAddress1 = new MailAddress("to1@test.com"); email.To.Add(toAddress1); MailAddress toAddress2 = new MailAddress("to2@test.com"); email.To.Add(toAddress2); MailAddress toAddress3 = new MailAddress("to3@test.com"); email.To.Add(toAddress3); MailAddress ccAddress1 = new MailAddress("cc1@test.com"); email.CC.Add(ccAddress1); MailAddress ccAddress2 = new MailAddress("cc2@test.com"); email.CC.Add(ccAddress2); MailAddress bccAddress1 = new MailAddress("bcc1@test.com"); email.Bcc.Add(bccAddress1); MailAddress bccAddress2 = new MailAddress("bcc2@test.com"); email.Bcc.Add(bccAddress2); MailAddress bccAddress3 = new MailAddress("bcc3@test.com"); email.Bcc.Add(bccAddress3); MailAddress bccAddress4 = new MailAddress("bcc4@test.com"); email.Bcc.Add(bccAddress4); email.Subject = "Email subject here"; email.Body = "Email body here"; // Set up the mail server SmtpClient smtpClient = new SmtpClient("mailservername"); smtpClient.Credentials = CredentialCache.DefaultNetworkCredentials; smtpClient.Timeout = 100; // Send the email smtpClient.Send(email); } } }
Slightly simpler version, still without a wrapper/facade
You could simplify the previous code by instantiating the MailAddress objects in-line. That will make the code a little shorter (it’s down to 26 lines now). But, there is still a lot of work that needs to be done (this code still needs to use three different classes, and have the mail “using” statements added), to send out an e-mail.
using System.Net; using System.Net.Mail; namespace DesignPatternDemos.Facade { public class MyClassForFacade { public void DoSomethingComplex_SlightlySimpler() { // Pretend there is business-logic here // Send an e-mail - complex version, with multiple "to", "cc", and "bcc" addresses. MailMessage email = new MailMessage(); email.From = new MailAddress("from@test.com"); email.To.Add(new MailAddress("to1@test.com")); email.To.Add(new MailAddress("to2@test.com")); email.To.Add(new MailAddress("to3@test.com")); email.CC.Add(new MailAddress("cc1@test.com")); email.To.Add(new MailAddress("cc2@test.com")); email.Bcc.Add(new MailAddress("bcc1@test.com")); email.Bcc.Add(new MailAddress("bcc2@test.com")); email.Bcc.Add(new MailAddress("bcc3@test.com")); email.Bcc.Add(new MailAddress("bcc4@test.com")); email.Subject = "Email subject here"; email.Body = "Email body here"; // Set up the mail server SmtpClient smtpClient = new SmtpClient("mailservername"); smtpClient.Credentials = CredentialCache.DefaultNetworkCredentials; smtpClient.Timeout = 100; // Send the email smtpClient.Send(email); } } }
Simplest version, using a wrapper/facade
By building a wrapper, I’ve reduced the previous code to 7 lines. These lines don’t need to create any objects, and you don’t need to include the mail-related “using” statements.
Here’s what the code looks like now:
using System.Net; using System.Net.Mail; namespace DesignPatternDemos.Facade { public class MyClassForFacade { public void DoSomethingComplexWithWrapper() { // Pretend there is business-logic here // Send an e-mail - version behind wrapper/facade, with multiple "to", "cc", and "bcc" addresses. EmailCreator.CreateEmailFrom("from@test.com") .To("to1@test.com", "to2@test.com", "to2@test.com") .CC("cc1@test.com", "cc2@test.com") .BCC("bcc1@test.com", "bcc2@test.com", "bcc3@test.com", "bcc4@test.com") .WithSubject("Email subject here") .WithBody("Email body here") .Send(); } } }
For this wrapper/facade, I created a class that uses a fluent interface. Your wrapper classes don’t need to use a fluent interface. It’s just the technique I chose to simplify this code.
This fluent interface could be improved; it doesn’t force any “grammar rules”. But, it’s good enough to show how a wrapper/facade works. This will show you how to create a powerful fluent interface.
For this wrapper, the EmailCreator class handles building all the objects needed to send out an e-mail. The interface (IEmailFluentInterface.cs) is needed to make EmailCreator into a class with a fluent interface.
EmailCreator.cs
using System.Net; using System.Net.Mail; namespace DesignPatternDemos.Facade { public class EmailCreator : IEmailFluentInterface { private MailMessage _mailMessage = new MailMessage(); private EmailCreator(string fromAddress) { _mailMessage.Sender = new MailAddress(fromAddress); } public static IEmailFluentInterface CreateEmailFrom(string fromAddress) { return new EmailCreator(fromAddress); } public IEmailFluentInterface From(string fromAddress) { return this; } public IEmailFluentInterface To(params string[] toAddresses) { foreach(string toAddress in toAddresses) { _mailMessage.To.Add(new MailAddress(toAddress)); } return this; } public IEmailFluentInterface CC(params string[] ccAddresses) { foreach(string ccAddress in ccAddresses) { _mailMessage.CC.Add(new MailAddress(ccAddress)); } return this; } public IEmailFluentInterface BCC(params string[] bccAddresses) { foreach(string bccAddress in bccAddresses) { _mailMessage.Bcc.Add(new MailAddress(bccAddress)); } return this; } public IEmailFluentInterface WithSubject(string subject) { _mailMessage.Subject = subject; return this; } public IEmailFluentInterface WithBody(string body) { _mailMessage.Body = body; return this; } public void Send() { // Set up the mail server SmtpClient smtpClient = new SmtpClient("mailservername"); smtpClient.Credentials = CredentialCache.DefaultNetworkCredentials; smtpClient.Timeout = 100; // Send the email smtpClient.Send(_mailMessage); } } }
IEmailFluentInterface.cs
using System.Net; using System.Net.Mail; namespace DesignPatternDemos.Facade { public interface IEmailFluentInterface { IEmailFluentInterface From(string fromAddress); IEmailFluentInterface To(params string[] toAddresses); IEmailFluentInterface CC(params string[] ccAddresses); IEmailFluentInterface BCC(params string[] bccAddresses); IEmailFluentInterface WithSubject(string subject); IEmailFluentInterface WithBody(string body); void Send(); } }
With a wrapper like EmailCreator, you can easily send out e-mails from any place in your programs. You’ll also be ready if the mail objects (MailMessage, MailAddress, and SmtpClient) ever change how they work.
Where I’ve found it useful
I actually encountered the e-mail message problem in a program I worked on several years ago. The .NET 2.0 framework changed the way they handled e-mail addresses, compared to how it worked in .NET 1.1.
I’ve also seen a large system that used a third-party UI control library. After several years without updating the library, the company decided to finally move to the latest version. It took several programmers, many days, to update the UI code to the new version. Once they were “done”, they still encountered problems over the next few weeks.
If we were using a wrapper, or facade, it would have been easier for us to handle those changes.
Source code for my design pattern lessons
5 Comments