Category Archives: Structural Patterns
Facade Pattern
Don’t shoot the messenger!
This is something that you are doing all the time. We just name it now. The Facade Pattern is a structural programming design pattern. To explain it in a nutshell:
A class contains many references to objects, which are invisible to the client. The client has a reduced command set to keep things simple.
The class receives the simple command and takes care about the real complexity behind the facade, which is presented to the client. Think of a cash dispenser. All you have to know is a few buttons. The legal structure, the buildings, the accounting, the risk etc. … all is invisible to the client, who only cares about getting cash at this very moment.
namespace FacadePattern { internal class Burger { public void Prepare() { } public void WarmUp() { } public void Wrap() { } } // class internal class Fries { public void Fry() { } public void KeepWarm() { } } // class internal class Drink { public enum eDrink { Coke, SevenUp, Orange, Apple, Milk, Tea, Coffee } public bool IsSugarFree { set; get; } public bool IsHot { set; get; } public void Fill(eDrink xDrink) { } } // class internal class Extras { public void AddSalt() { } public void AddKetchup() { } public void AddMayo() { } public void AddNapkin() { } } // class public class MealFacade { private Burger _Burger = new Burger(); private Fries _Fries = new Fries(); private Drink _Drink = new Drink(); private Extras _Extras = new Extras(); public void MakeClientHappy() { _Drink.IsHot = false; _Drink.IsSugarFree = true; _Drink.Fill(Drink.eDrink.Coke); _Fries.Fry(); _Burger.Prepare(); _Burger.Wrap(); _Extras.AddKetchup(); _Extras.AddSalt(); _Extras.AddNapkin(); } // } // class class Program { static void Main(string[] args) { MealFacade lBurgerMeal = new MealFacade(); lBurgerMeal.MakeClientHappy(); } // main } // class } // namespace
Adapter Pattern
Once again it sounds more difficult than it actually is.
What is an Adapter?
An Adapter sits in between two objects that cannot be changed and cannot talk to each other. It is like the American and British power socket:
- The socket shape and voltage are different.
- You cannot change the situation. The source and the target are static.
- An adapter can connect the two systems.
Adapters can also connect to several source or target objects. Let’s imagine a database is split in two. An Adapter could connect to the two separate databases and return the result as if it was just one. Using several source objects is uncommon. It does make sense, when events from two or more sources need to occur before the access to the target object can take place.
I’d say that the Adapter pattern is not more than a workaround, it is a compromise to avoid other problems. There is a difference between chewing gum and glue. Both can hold pieces together … somehow.
Imagine a British datacenter with 1000 (US->UK) power socket adapters. It would work, but don’t wonder, when someone stumbles over a adapter and disconnects something important.
(The WPF value converter is similar, not the same though. The converter eg. accepts a string and returns a double.)
Here is a short example:
namespace demo { public interface IPrinterDriver { void Print(string xText); } // interface // Client public class PrinterDriver : IPrinterDriver { private readonly IPrinterDriver _Driver; public PrinterDriver(IPrinterDriver xDriver) { _Driver = xDriver; } public void Print(string xText) { _Driver.Print(xText); } } // class // Adaptee public class Windows3_1_MatrixPrinterDriver { public void Init(string xCommandSequence) { ... } public void ParkPrintHead() { ... } public void Print(string xText) { ... } } // class // Adapter public class Win8_to_Win31_PrinterDriverAdapter : IPrinterDriver { private readonly Windows3_1_MatrixPrinterDriver _Driver = new Windows3_1_MatrixPrinterDriver(); public void Print(string xText) { _Driver.Init("§50asabpwebts.dae§"); _Driver.Print(xText); _Driver.ParkPrintHead(); } // } // class class Program { static void Main(string[] args) { Win8_to_Win31_PrinterDriverAdapter lAdapter = new Win8_to_Win31_PrinterDriverAdapter(); PrinterDriver lDriver = new PrinterDriver(lAdapter); lDriver.Print("Hello World!"); } // } // class } // namespace
In many examples the adapter inherits the Adaptee AND the Interface, which would then look like this:
public class Win8_to_Win31_PrinterDriverAdapter : IPrinterDriver, Windows3_1_MatrixPrinterDriver { ... }
I disagree with such approach and rather use create a private readonly field instead. It is easier to avoid naming conflicts then.
Cascade pattern / Method chaining
Today, I am going to explain a simple programming pattern step by step.
Often the cascade pattern can be found in connection with consecutive data manipulation. It has many names. In C# I would put it in the same chapter as Extension Methods.
But let us start at the very beginning. Genesis 🙂
This is a simple integer calculation.
int r0 = 5; r0 = ((((r0 + 2) * 4) - 8) / 2) + 1; Console.WriteLine("Result is " + r0); // 11
We could break it down into many separate calculation steps …
int r1 = 5; r1 += 2; r1 *= 4; r1 -= 8; r1 /= 2; r1 += 1; Console.WriteLine("Result is " + r1); // 11
… and build a class to perform reoccurring calculations.
public class Classic { static public int add(int a, int b) { return a + b; } static public int sub(int a, int b) { return a - b; } static public int mul(int a, int b) { return a * b; } static public int div(int a, int b) { return a / b; } } // class int r2 = 5; r2 = Classic.add(r2, 2); r2 = Classic.mul(r2, 4); r2 = Classic.sub(r2, 8); r2 = Classic.div(r2, 2); r2 = Classic.add(r2, 1); Console.WriteLine("Result is " + r2); // 11
Well, this is nice. But the code is clumsy. We could overload operators. Anyhow, this is not the way I would like to go today. What about a memory variable in form of a property called “Result”.
public class Cascade1 { public int Result { get; private set; } public Cascade1(int x) { Result = x; } public Cascade1 add(int x) { Result += x; return this; } public Cascade1 sub(int x) { Result -= x; return this; } public Cascade1 mul(int x) { Result *= x; return this; } public Cascade1 div(int x) { Result /= x; return this; } } // class int c1 = new Cascade1(5) .add(2) .mul(4) .sub(8) .div(2) .add(1) .Result; Console.WriteLine("Result is " + c1); // 11
This looks much better, doesn’t it?
We replace the integers by a simple class, which only has one public field called “Age”.
public class Data { public int Age; } // class
We add IENumberable as parameter. Now, the program looks neat and more flexible.
public class Cascade2 { public static void add(IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age += xValue; } public static void sub(IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age -= xValue; } public static void mul(IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age *= xValue; } public static void div(IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age /= xValue; } } // class List<Data> lList = new List<Data>(); for (int i = 0; i < 10; i++) lList.Add(new Data() { Age = i }); Cascade2.add(lList, 2); Cascade2.mul(lList, 4); Cascade2.sub(lList, 8); Cascade2.div(lList, 2); Cascade2.add(lList, 1); Console.Write("Array result is "); lList.ForEach(x => Console.Write(x.Age + " "));
But once again we face too many parameters. Should we add a memory field? No, C# offers Extension Methods. This is the way to go!
public static class Cascade3 { public static IEnumerable<Data> add(this IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age += xValue; return xIENumberable; } // public static IEnumerable<Data> sub(this IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age -= xValue; return xIENumberable; } // public static IEnumerable<Data> mul(this IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age *= xValue; return xIENumberable; } // public static IEnumerable<Data> div(this IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age /= xValue; return xIENumberable; } // } // class List<Data> lList = new List<Data>(); for (int i = 0; i < 10; i++) lList.Add(new Data() { Age = i }); lList.add(2) .mul(4) .sub(8) .div(2) .add(1); Console.Write("Array result is "); lList.ForEach(x => Console.Write(x.Age + " "));
Each List object can now use the extension methods. In C# you most likely have come across such pattern when using the namespace System.Linq. Adding this namespace automatically enables many methods for lists (IENumerable) and arrays. Here is an example of that namespace. You can chain together methods. Make sure the return parameter points to the same list each time, otherwise the chain is broken. For instance a Sum() would return a number rather an IENumerable, thus breaking the chain.
List<Data> lList = new List<Data>(); for (int i = 0; i < 10; i++) lList.Add(new Data() { Age = i }); // using System.Linq; List<Data> lResult = lList.Where(x => x.Age % 2 == 0).Take(10).ToList(); Console.Write("Array result is "); lResult.ForEach(x => Console.Write(x.Age + " "));
And here is the entire source code in one piece.
using System; using System.Collections.Generic; using System.Linq; namespace CascadePattern { public class Data { public int Age; } // class public static class Cascade3 { public static IEnumerable<Data> add(this IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age += xValue; return xIENumberable; } // public static IEnumerable<Data> sub(this IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age -= xValue; return xIENumberable; } // public static IEnumerable<Data> mul(this IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age *= xValue; return xIENumberable; } // public static IEnumerable<Data> div(this IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age /= xValue; return xIENumberable; } // } // class class Program { public class Classic { static public int add(int a, int b) { return a + b; } static public int sub(int a, int b) { return a - b; } static public int mul(int a, int b) { return a * b; } static public int div(int a, int b) { return a / b; } } // class public class Cascade1 { public int Result { get; private set; } public Cascade1(int x) { Result = x; } public Cascade1 add(int x) { Result += x; return this; } public Cascade1 sub(int x) { Result -= x; return this; } public Cascade1 mul(int x) { Result *= x; return this; } public Cascade1 div(int x) { Result /= x; return this; } } // class public class Cascade2 { public static void add(IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age += xValue; } // public static void sub(IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age -= xValue; } // public static void mul(IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age *= xValue; } // public static void div(IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age /= xValue; } // } // class static void Main(string[] args) { int r0 = 5; r0 = ((((r0 + 2) * 4) - 8) / 2) + 1; Console.WriteLine("Result is " + r0); // 11 int r1 = 5; r1 += 2; r1 *= 4; r1 -= 8; r1 /= 2; r1 += 1; Console.WriteLine("Result is " + r1); // 11 int r2 = 5; r2 = Classic.add(r2, 2); r2 = Classic.mul(r2, 4); r2 = Classic.sub(r2, 8); r2 = Classic.div(r2, 2); r2 = Classic.add(r2, 1); Console.WriteLine("Result is " + r2); // 11 int c1 = new Cascade1(5) .add(2) .mul(4) .sub(8) .div(2) .add(1) .Result; Console.WriteLine("Result is " + c1); // 11 List<Data> lList = new List<Data>(); for (int i = 0; i < 10; i++) lList.Add(new Data() { Age = i }); Cascade2.add(lList, 2); Cascade2.mul(lList, 4); Cascade2.sub(lList, 8); Cascade2.div(lList, 2); Cascade2.add(lList, 1); Console.Write("Array result is "); lList.ForEach(x => Console.Write(x.Age + " ")); Console.WriteLine(); lList.Clear(); for (int i = 0; i < 10; i++) lList.Add(new Data() { Age = i }); lList.add(2) .mul(4) .sub(8) .div(2) .add(1); Console.Write("Array result is "); lList.ForEach(x => Console.Write(x.Age + " ")); Console.WriteLine(); // using System.Linq; lList.Clear(); for (int i = 0; i < 50; i++) lList.Add(new Data() { Age = i }); List<Data> lResult = lList.Where(x => x.Age % 2 == 0).Take(10).ToList(); Console.Write("Array result is "); lResult.ForEach(x => Console.Write(x.Age + " ")); Console.ReadLine(); } // } // class } // namespace
example output:
Result is 11
Result is 11
Result is 11
Result is 11
Array result is 1 3 5 7 9 11 13 15 17 19
Array result is 1 3 5 7 9 11 13 15 17 19
Array result is 0 2 4 6 8 10 12 14 16 18