Design Patterns explained

Types of Design Patterns

Creational Design Patterns

A creational design pattern is focused towards how to instantiate an object or group of related objects.

Wikipedia says :

In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation.

Simple Factory

Wikipedia says :

In object-oriented programming (OOP), a factory is an object for creating other objects – formally a factory is a function or method that returns objects of a varying prototype or class from some method call, which is assumed to be "new".

In plain words, a factory in its simplest form (it's also exists abstract factory pattern and method factory pattern) is a class which has a method that returns differents type of object.

Real world example :

Consider you are building vehicles (like cars, motorbikes, trucks and others), it would be painfull if each time you need to put the wheels on the vehicle you need to think about it and start making the new wheels from the start. Instead you get them made from a factory.

Programmatic example :


/// <summary>
/// Contract each wheel for a vehicle have to respect
/// </summary>
public interface IVehicleWheel{
	
	int GetWidth();
	int GetDiameter();
	
}

/// <summary>
/// A wheel for a car
/// </summary>
public class CarWheel : IVehicleWheel {

	/// <summary>
	/// Width of the wheel in inches
	/// </summary>
	public int Width { get; }
	
	/// <summary>
	/// Diameter of the wheel in inches
	/// </summary>
	public int Diameter { get; }
	
	/// <summary>
	/// New instance of a car wheel
	/// </summary>
	public CarWheel(int width, int diameter) {
	
		Width = width;
		Diameter = diameter;
		
	}
	
	public int GetWidth() => Width;
	
	public int GetDiameter() => Diameter;
	
}

/// <summary>
/// Class to instanciate all the wheels you need
/// </summary>
public static class WheelFactory {

	public static IVehicleWheel MakeCarWheel(int width, int diameter) => new CarWheel(width, diameter);

}

And then it can be used as :


IVehicleWheel wheel = WheelFactory.MakeCarWheel(15, 30);

When to use it ?

When creating an object isn't just a few assignements but involves some business logic, it makes sense to put the logic in a dedicated factory instead of repeating the code everywhere.

Factory Method

Wikipedia says :

In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.

In plain words, a Factory Method provides a way to delegate the instanciation logic to subclasses. It defines an interface for creating an object but let's his subclasses implement this interface and decide which class to instanciate.

Real world example :

Consider a football player, it's impossible for one person to be very good in each game position, so you have to delegate some parts of the game to others players.

Programmatic example :


#region Skills

public abstract class Skill
{

}

public class Acrobat : Skill {

}

public class Dribbler : Skill {

}

public class DistanceShooter : Skill {

}

public class Speedster : Skill {

}

public class Tackling : Skill {

}

public class Tactician : Skill {

}

public class ClinicalFinisher : Skill {

}

public class Strenght : Skill {

}

public class Playmaker : Skill {

}

public class Engine : Skill {

}

public class Reflex : Skill {

}

public class Tall : Skill {

}

public class Springiness : Skill {

}

public class ExtremeConcentration : Skill {

}

#endregion

#region Players

public abstract class Player()
{
	public List<Skill> Skills { get; protected set;}
	
	// Factory Method
    public abstract void CreateSkills();

	public Player() {
		
		CreateSkills();
		
	}
}

public class Defender : Player {

	// Factory Method implementation
	public override void CreateSkills(){
	
		Skills = new ListList<Skill>();
		
		Skills.Add(new Strenght());
		Skills.Add(new Tackling());
		Skills.Add(new Tall());
	
	}
	
}

public class Midfielder : Player {

	// Factory Method implementation
	public override void CreateSkills(){
	
		Skills = new ListList<Skill>();
		
		Skills.Add(new Engine());
		Skills.Add(new Playmaker());
		Skills.Add(new Tactician());
	
	}
	
}

public class Forward : Player {

	// Factory Method implementation
	public override void CreateSkills(){
	
		Skills = new ListList<Skill>();
		
		Skills.Add(new ClinicalFinisher());
		Skills.Add(new Speedster());
		Skills.Add(new Dribbler());
		Skills.Add(new Acrobat());
	
	}
	
}

public class GoalKeeper : Player {

	// Factory Method implementation
	public override void CreateSkills(){
	
		Skills = new ListList<Skill>();
		
		Skills.Add(new Reflex());
		Skills.Add(new Tall());
		Skills.Add(new Springiness());
		Skills.Add(new ExtremeConcentration());
	
	}
	
}

#endregion

  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
	  // Create a list of players
      List<Player> players = new List<Player>();
	  players.Add(new GoalKeeper());
	  players.Add(new Defender());
	  players.Add(new Midfielder());
	  players.Add(new Forward());
 
      // Display player skills
      foreach (Player player in players)
      {
        Console.WriteLine("\n" + player.GetType().Name + "--");
        foreach (Skill skill in player.Skills)
        {
          Console.WriteLine(" " + skill.GetType().Name);
        }
      }
 
      // Wait for user
      Console.ReadKey();
    }
  }

When to use it ?

When there is some generic processing in a class but you doesn't know what exact subclass it might need, so you let the child class decide.

Abstract Factory

Wikipedia says :

The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes

In plain words, an abstract factory is a factory of factories. It's a class that groups the individual but related/dependent factories together without specifying their concrete classes.

Real world example :

To stay in the football world, we still have our different kind of players with their own skills, let consider now the coaches. The differents players doesn't need the same coach to progress. A goalkeeper needs a specific coach to his position, as a forward player needs some coaches to work on his shoot, his dribble and his velocity. So as we have different kind of players, we have different kinf of instructors with their specialities and as you can see, there is a dependency between the players and the coaches.

Programmatic example :


#region Coachs

public abstract class Coach {

}

public class GoalKeeperCoach : Coach {
}

public class DribbleCoach : Coach {
}

public class ShootCoach : Coach {
}

public class TacklingCoach : Coach {
}

public class TacticianCoach : Coach {
}

public class PassCoach : Coach {
}

public class MuscleDevelopmentCoach : Coach {
}

#endregion

#region Skills

public abstract class Skill
{

}

public class Acrobat : Skill {

}

public class Dribbler : Skill {

}

public class Shooter : Skill {

}

public class DistanceShooter : Skill {

}

public class Speedster : Skill {

}

public class Tackling : Skill {

}

public class Tactician : Skill {

}

public class ClinicalFinisher : Skill {

}

public class Strenght : Skill {

}

public class Playmaker : Skill {

}

public class Engine : Skill {

}

public class Reflex : Skill {

}

public class Tall : Skill {

}

public class Springiness : Skill {

}

public class ExtremeConcentration : Skill {

}

public class ClinicalPasser : Skill {

}

#endregion

#region Factories

public abstract class PlayerFactory {

	public abstract Player CreatePlayer();
	
	public abstract List<Coach> CreateCoachs();
	
}

public class GoalKeeperFactory : PlayerFactory {

	public override Player CreatePlayer() {
	
		GoalKeeper player = new GoalKeeper();
		player.Skills = new List<Skill>();
		player.Skills.Add(new Tall());
		player.Skills.Add(new Reflex());
		player.Skills.Add(new ExtremeConcentration());
		player.Skills.Add(new Springiness());
		return player;
	
	}
	
	public override List<Coach> CreateCoachs() {
		List<Coach> ret = new List<Coach>();
		ret.Add(new GoalKeeperCoach());
		return ret;
	}

}

public class DefenderFactory : PlayerFactory {

	public override Player CreatePlayer() {
	
		GoalKeeper player = new GoalKeeper();
		player.Skills.Add(new Strenght());
		player.Skills.Add(new Tall());
		player.Skills.Add(new Tackling());
		return player;
	
	}
	
	public override List<Coach> CreateCoachs() {
		List<Coach> ret = new List<Coach>();
		ret.Add(new TacklingCoach());
		ret.Add(new MuscleDevelopmentCoach());
		return ret;
	}

}

public class MidfielderFactory : PlayerFactory {

	public override Player CreatePlayer() {
	
		GoalKeeper player = new GoalKeeper();
		player.Skills.Add(new Dribble());
		player.Skills.Add(new Tactician());
		player.Skills.Add(new Tackling());
		player.Skills.Add(new ClinicalPasser());
		player.Skills.Add(new Playmaker());
		return player;
	
	}
	
	public override List<Coach> CreateCoachs() {
		List<Coach> ret = new List<Coach>();
		ret.Add(new TacklingCoach());
		ret.Add(new DribbleCoach());
		ret.Add(new PassCoach());
		ret.Add(new TacticianCoach());
		return ret;
	}

}

public class ForwardFactory : PlayerFactory {

	public override Player CreatePlayer() {
	
		GoalKeeper player = new GoalKeeper();
		player.Skills.Add(new Speedster());
		player.Skills.Add(new Acrobat());
		player.Skills.Add(new Shooter());
		player.Skills.Add(new ClinicalFinisher());
		player.Skills.Add(new Dribble());
		return player;
	
	}
	
	public override List<Coach> CreateCoachs() {
		List<Coach> ret = new List<Coach>();
		ret.Add(new ShootCoach());
		ret.Add(new DribbleCoach());
		return ret;
	}

}

#endregion

#region Players

public abstract class Player()
{
	public List<Skill> Skills { get; set;}
	
	public abstract string GetDescription();
}

public class Defender : Player {

	public override string GetDescription() => $("I am a defender, I have {Skills.Count} skills");
	
}

public class Midfielder : Player {

	public override string GetDescription() => $("I am a midfielder, I have {Skills.Count} skills");
	
}

public class Forward : Player {

	public override string GetDescription() => $("I am a forward player, I have {Skills.Count} skills");
	
}

public class GoalKeeper : Player {

	public override string GetDescription() => $("I am a goalkeeper, I have {Skills.Count} skills");
	
}

#endregion

  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
	  // Create a goalkeeper
      GoalKeeperFactory gkFactory = new GoalKeeperFactory();
	  Player goalkeeper = gkFactory.CreatePlayer();
	  List<Coach> gkCoachs = gkFactory.CreateCoachs();
	  Console.WriteLine($"{goalkeeper.GetDescription()} and I need {gkCoachs.Count} coachs :");
	  foreach(Coach c in gkCoachs) {
		Console.WriteLine("   - " + c.GetType().Name);
	  }
	  
      // Wait for user
      Console.ReadKey();
    }
  }

When to use it ?

Still to delegate and encapsulate the creation logic complexity, but when you have interrelated dependencies.

Builder

Wikipedia says :

The builder pattern is an object creation software design pattern with the intentions of finding a solution to the telescoping constructor anti-pattern.

In plain words, a builder avoid the constructor pollution with options. It allows you to create the same object with different configurations.

Real world example :

Imagine you are at a Lamborghini's dealer and you order a car, let's say the Aventador. If the seller brought a car to you without any questions, this is an example of a simple factory. But there are cases when the creation logic might involve more steps, for example in this case, you probably want a customized car. Which color do you want ? Which options ? Wood or aluminium finish for the dashboard ? Which motor power ? In such cases builder pattern comes to the rescue.

Programmatic example :

Using a telescoping constructor anti-pattern :


public class Car {

	public string Manufacturer {get;set;}
	public string Model {get;set;}
	public int Doors { get; set; } = 5;
	public string Color { get; set; } = "black";
	public string DashboardFinish { get; set; } = "wood";
	
	public Car(string manufacturer, string model, int? doors, string color, string dashboardFinish){
	
		Manufacturer = manufacturer;
		Model = model;
	
		if(doors.HasValue){
			Doors = doors;
		}
		
		if(!string.IsNullOrWhiteSpace(color)){
			Color = color:
		}
		
		if(!string.IsNullOrWhiteSpace(dashboardFinish)){
			DashboardFinish = dashboardFinish:
		}
	}

}

Using a builder design pattern :


public class Car {

	public string Manufacturer {get;set;}
	public string Model {get;set;}
	public int Doors { get; set; } = 5;
	public string Color { get; set; } = "black";
	public string DashboardFinish { get; set; } = "wood";
	
	public Car(string manufacturer, string model){
	
		Manufacturer = manufacturer;
		Model = model;
	}

}

public class CarBuilder {

	private Car Car { get; set; }
	
	public CarBuilder(string manufacturer, string model){
		Car = new Car(manufacturer, model);
	}
	
	public void SetNbDoors(int count) => car.Doors = count;
	
	public void SetColor(string color) => car.Color = color;
	
	public void SetDashboardFinish(string finish) => car.DashboardFinish = finish;
	
	public Car Build() => return Car;

}

And you can use it like :


CarBuilder carBuilder = new CarBuilder("Lamborghini", "Aventador");
carBuilder.SetNbDoors(3);
carBuilder.SetColor("orange");
Car myDreamCar = carBuilder.Build();

When to use it ?

When the creation logic of an object includes several steps. This is the difference between a factory, in which the creation logic is a one step process, and a builder who is used when the same construction process can create different representations of the same object.

Prototype

Wikipedia says :

The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects.

In plain words, a prototype creates an object based on an existing object through cloning.

Real world example :

Remember dolly? The sheep that was cloned! Lets not get into the details but the key point here is that it is all about cloning

When to use it ?

When you need the exact same object as an existing object.

Singleton

Wikipedia says :

In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system.

In plain words, a singleton ensures that only one instance of an object is ever created.

Real world example :

Consider there is only one Universe, all the solar systems and planets are sharing the same Universe, so the Universe is a singleton.

Programmatic example :


public class Universe 
{
    /// <summary>
    /// The speed of light in m/s
    /// </summary>
	public const int SpeedOfLight = 300000000;
	
	private static Universe instance;
	
	private Universe() {}
	
	public static Universe Instance
	{
		get
		{
			if(instance == null){
				instance = new Universe();
			}
			
			return instance;
		}
	}

}

When to use it ?

When you need that an object have to have only one instance at a time in your application (file logger, ...)

Structural Design Patterns

Wikipedia says :

In software engineering, structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities.

In plain words :

The concern of the structural patterns is how the entities can use each other.

Adapter

Wikipedia says :

In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code.

In plain words, an adapter let's you wrap an otherwise incompatible object in an adapter to make it compatible with another class.

Real world example :

A good example is when you need to plug something in a foreign country, let's say France and Scotland. This both countries have differents plug interface, so you absolutely not plug your french charger in a plug in Scotland. So you go to a store and buy an adapter : a charger who have a side to communicate with a French charger, and another who can communicate with a scottish one, without modify any of this both objects.

Programmatic example :


public class Player
{
	public string Name { get; }
	public DateTime Birthday { get; }
	public int Level { get; }
	
	// Pace
	public int SprintSpeed { get; }
	public int Acceleration { get; }
	
	// Shooting
	public int Finishing { get; }
	public int LongShots { get; }
	public int ShotPower { get; }
	public int AttackPositioning { get; }
	public int Penalties { get; }
	public int Volleys { get; }
	
	// Passing
	public int ShortPassing { get; }
	public int LongPassing { get; }
	public int Vision { get; }
	public int Crossing { get; }
	public int FKAccuracy { get; }
	public int Curve { get; }
	
	// Dribbling
	public int Dribbling { get; }
	public int BallControl { get; }
	public int Agility { get; }
	public int Balance { get; }
	public int Reactions { get; }
	
	// Defending
	public int Marking { get; }
	public int StandTackle { get; }
	public int Interceptions { get; }
	public int HeadingAccuracy { get; }
	public int SlideTackle { get; }
	
	// Physical
	public int Strength { get; }
	public int Aggression { get; }
	public int Stamina { get; }
	public int Jumping { get; }
	
	// Mental
	public int Concentration { get; }
	public int Leadership { get; }
	public int SelfControl { get; }
	public int Presence { get; }
	
	//
	public virtual string GetPresentationMessage() => $"My name is {Name}, I am born in {Birthday.Year} and I am a {Level >= 80 ? "very good" : Level >= 65 ? "good" : string.Empty} football player.";
}

public abstract class Skill
{}

public class Shooter : Skill
{}

public class Dribbler : Skill
{}

public class Leader : Skill
{}

public class Wall : Skill
{}

public class Athlete : Skill
{}

/// <summary>
/// The 'Adapter' class
/// </summary>
public class SkilledPlayer : Player
{
	private SkillBank _skillBank = new SkillBank();
	
	public SkilledPlayer()
		: base()
	{
	}
	
	public override string GetPresentationMessage()
	{
		string ret = base.GetPresentationMessage();
		
		List<Skill> skills = _skillBank.GetSkills(this);
		
		if(skills == null || skills.Count == 0)
			return ret;
			
		foreach(Skill skill in skills){
			ret += $"I am a {skill.GetType().Name}. ";
		}
		
		return ret;
	}
}

/// <summary>
/// The 'Adaptee' class
/// <summary>
public class SkillBank
{
	private const int _skillMinLevel = 80;
	
	private const int _skilledPlayerMinGlobalLevel = 55;
	
	public List<Skill> GetSkills(Player player)
	{
		List<Skill> ret = new List<Skill>();
		
		if(player.Level < _skilledPlayerMinGlobalLevel){
			return ret;
		}

		if(HasShooterSkill(player))
			ret.Add(new Shooter());

		if(HasDefenderSkill(player))
			ret.Add(new Wall());
			
		return ret;
	}
	
	private bool HasShooterSkill(Player player){
		if(player.Finishing >= _skillMinLevel && player.ShotPower >= _skillMinLevel && player.AttackPositioning >= _skillMinLevel)
			return true;
			
		return false;
	}
	
	private bool HasDefenderSkill(Player player){
		int i = 0;
		
		if(player.Marking >= _skillMinLevel)
			i = i++;
		
		if(player.StandTackle >= _skillMinLevel)
			i = i++;
		
		if(player.SlideTackle >= _skillMinLevel)
			i = i++;
		
		if(player.HeadingAccuracy >= _skillMinLevel)
			i = i++;
		
		if(player.Interceptions >= _skillMinLevel)
			i = i++;
		
		if(player.Strength >= _skillMinLevel)
			i = i++;
		
		if(player.Aggression >= _skillMinLevel)
			i = i++;
			
		if(i >= 5)
			return true;
			
		return false;
	}
}

When to use it ?

When you need that some classes have to collaborate but have incompatible interfaces.

Bridge

Wikipedia says :

The bridge pattern is a design pattern used in software engineering that is meant to "decouple an abstraction from its implementation so that the two can vary independently"

In plain words, the bridge pattern is about preferring composition over inheritance.

Real world example :

In the football management game you develop, you can pick any Premier League team to manage it. Each team has his own logo, his graphic theme and other graphical elements. Your game has 25 differents user interfaces so what are you doing ? You develop all the interface in all the themes available, and display the interfaces corresponding to the team the user choose ? Or you develop the interfaces and the themes independently, and load the good theme when you display a user interface ? If you choose the second option, it's a Bridge pattern. Otherwise, if you choose the first option, it's a Mess anti-pattern and just stay away from me...

Programmatic example :


/// 
/// The 'Bridge/Implementor' interface
/// 
public interface IMessageSender
{
	void Send(string subject, string body);
}

/// 
/// The 'ConcreteImplementor' class
/// 
public sealed class EmailSender : IMessageSender
{
	public void Send(string subject, string body)
	{
		// Business logic to send a mail
		Console.WriteLine($"Email : {subject} - {body}");
	}
}

/// 
/// The 'ConcreteImplementor' class
/// 
public sealed class SMSSender : IMessageSender
{
	public void Send(string subject, string body)
	{
		// Business logic to send a SMS
		Console.WriteLine($"SMS : {subject} - {body}");
	}
}

/// 
/// The 'Abstraction' class
/// 
public abstract class Message
{
	public string Subject { get; set; }
	public string Body { get; set; }
	
	public IMessageSender Sender { get; set; }
	public abstract void Send();
}

/// 
/// The 'RefinedAbstraction' class
/// 
public sealed class PlayerMessage : Message
{
	public string Name { get; set; }
	public int Level { get; set; }
	
	public PlayerMessage(string name, int level)
	:base()
	{
		Name = name;
		Level = level;
	}
	
	public override void Send()
	{
		string fullBody = $"The player {Name} (level {Level}) sends the message: {Body}";
		Sender.Send(Subject, fullBody);
	}
}

/// 
/// The 'RefinedAbstraction' class
/// 
public sealed class CoachMessage : Message
{
	public override void Send()
	{
		MessageSender.Send(Subject, Body);
	}
}

  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
	  IMessageSender emailSender = new EmailSender();
	  IMessageSender smsSender = new SMSSender();
	  
	  // Send a player message
	  
	  Message msg1 = new PlayerMessage("Zidane", 95);
	  msg1.Subject = "Test message";
	  msg1.Body = "This is the body of the test message.";
	  
	  // Send - email
	  msg1.Sender = emailSender;
	  msg1.Send();
	  
	  // Send - SMS
	  msg1.Sender = smsSender;
	  msg1.Send();
	  
	  // Send a coach message
	  
	  Message msg2 = new CoachMessage();
	  msg2.Subject = "Test message";
	  msg2.Body = "This is the body of the test message.";
	  
	  // Send - email
	  msg2.Sender = emailSender;
	  msg2.Send();
	  
	  // Send - SMS
	  msg2.Sender = smsSender;
	  msg2.Send();
 
      // Wait for user
      Console.ReadKey();
    }
  }

Composite

Wikipedia says :

In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes that a group of objects is to be treated in the same way as a single instance of an object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.

In plain words, the composite pattern composes objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

Real world example :

Think about the Universe. It is composed by planets, stars, galaxies, and so much things. All this things are space elements with common attributes, like a Name, a density, a chimical composition, ... and it exists a hierarchy between them : a universe owns some galaxies, who owns some systems who owns some planets.

Programmatic example :


public abstract class SpaceElement
{
	public string Name { get; set; }
	
	public SpaceElement(string name){
		Name = name;
	}
	
	public abstract void Display();
}

public class Universe : SpaceElement
{
	public IEnumerable Galaxies { get; set; }
	
	public void AddGalaxy(Galaxy g){
		Galaxies.Add(g);
	}
	
	public override void Display()
	{
		Console.WriteLine($"{Name} - I am the Universe");
		Console.WriteLine($"I have {Galaxies.Count()} galaxies :");
		foreach(SpaceElement g in Galaxies){
			g.Display();
		}
	}
}

public class Galaxy : SpaceElement
{
	public IEnumerable SolarSystems { get; set; }
	
	public void AddSystem(SolarSystem s){
		SolarSystems.Add(s);
	}
	
	public override void Display()
	{
		Console.WriteLine($"{Name} - Galaxy");
		Console.WriteLine($"I have {SolarSystems.Count()} solar systems :");
		foreach(SpaceElement s in SolarSystems){
			s.Display();
		}
	}
}

public class SolarSystem : SpaceElement
{
	public IEnumerable Stars { get; set; }
	public IEnumerable Planets { get; set; }
	
	public void AddStar(Star s){
		Stars.Add(s);
	}
	
	public void AddPlanet(Planet p){
		Planets.Add(p);
	}
	
	public override void Display()
	{
		Console.WriteLine($"{Name} - SolarSystem");
		Console.WriteLine($"I have {Stars.Count()} stars :");
		foreach(SpaceElement s in Stars){
			s.Display();
		}
		Console.WriteLine($"I have {Planets.Count()} planets :");
		foreach(SpaceElement p in Planets){
			p.Display();
		}
	}
}

public class Star : SpaceElement
{
	public override void Display() => Console.WriteLine($"{Name} (star)");
}

public class Planet : SpaceElement
{
	public override void Display() => Console.WriteLine($"{Name} (planet)");
}

  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
	  SpaceElement earth = new Planet("Earth");
	  
	  SpaceElement sun = new Star("Sun");
	  
	  SolarSystem solarSystem = new SolarSystem("Solar system");
	  solarSystem.AddStar(sun);
	  solarSystem.AddPlanet(earth);
	  
	  SpaceElement milkyWay = new Galaxy("Milky Way");
	  milkyWay.AddSystem(solarSystem);
	  
	  SpaceElement universe = new Universe("Our Universe");
	  universe.AddGalaxy(milkyWay);
	  
	  universe.Display();
 
      // Wait for user
      Console.ReadKey();
    }
  }

Decorator

Wikipedia says :

In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern.

In plain words, the decorator pattern lets you dynamically attach additional responsabilities to an object. A decorator is an alternative to inheritance.

Programmatic example :


public class RentalAgency
{
	public string Name { get; set; }
	public IEnumerable<Vehicle> Vehicles { get; set; }
}

public abstract class Vehicle
{
	public string Model { get; set; }
	public string Manufacturer { get; set; }
	public int NumCopies { get; set; }
	
	public Vehicle(string manufacturer, string model, int copies)
	{
		Manufacturer = manufacturer;
		Model = model;
		NumCopies = copies;
	}
	
	public abstract void Display();
}

public class Car : Vehicle
{
	public Car(string manufacturer, string model, int copies)
	{
		Manufacturer = manufacturer;
		Model = model;
		NumCopies = copies;
	}
	
	public override void Display() => Console.WriteLine($"(car) {Manufacturer} {Model} - Copies: {NumCopies}");
}

public class Truck : Vehicle
{
	public int Capacity { get; set; }

	public Truck(string manufacturer, string model, int copies, int capacity)
	{
		Manufacturer = manufacturer;
		Model = model;
		NumCopies = copies;
		Capacity = capacity;
	}
	
	public override void Display() => Console.WriteLine($"(truck) {Manufacturer} {Model} - Capacity: {Capacity} - Copies: {NumCopies}");
}

/// <summary>
/// The 'Decorator' abstract class
/// </summary>
public abstract class Decorator : Vehicle
{
	protected Vehicle vehicle;

	public Decorator(Vehicle v)
	{
    	vehicle = v;
	}

	public override void Display() => vehicle.Display();
}

/// <summary>
/// The 'ConcreteDecorator' class
/// </summary>
public class Borrowable : Decorator
{
	protected List<string> borrowers = new List<string>();
	
	public Borrowable(Vehicle vehicle)
	  : base(vehicle)
	{ }
	
	public void Borrow(string name)
	{
		borrowers.Add(name);
		vehicle.NumCopies--;
	}
	
	public void Return(string name)
	{
		borrowers.Remove(name);
		vehicle.NumCopies++;
	}
	
	public override void Display()
	{
		base.Display();
		
		if(borrowers == null || borrowers.Count == 0)
			return;
			
		Console.WriteLine(borrowers.Count + "borrower" + (borrowers.Count > 1 ? "s" : string.Empty));
		
		foreach(string borrower in borrowers)
			Console.WriteLine(" - " + borrower);
	}
}

  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
	  Car aventador = new Car("Lamborghini", "Aventador", 8);
	  aventador.Display();
	  
	  Car carerra = new Car("Porshe", "Carrera 4", 6);
	  carerra.Display();
	  
	  // Make the Lamborghini Aventador borrowable
	  Borrowable borrowableAventador = new Borrowable(aventador);
	  borrowableAventador.Borrow("Customer #1");
	  borrowableAventador.Borrow("Customer #2");
	  
	  borrowableAventador.Display();
 
      // Wait for user
      Console.ReadKey();
    }
  }

When to use it ?

When you want to add some behaviors to an object without modify or extend it.

Facade

Wikipedia says :

A facade is an object that provides a simplified interface to a larger body of code, such as a class library.

In plain words, facade pattern provides a simplified interface to a complex subsystem.

Real world example :

Facade are everywhere ! When you turn on your car you just turn a key, such a simple movement. But there are dozens of things who appends in the car to turn on the motor. The key's movement hides all the subsystem complexity, it's a facade.

Programmatic example :


public class Car
{
	public string Model { get; set; }
	public string Manufacturer { get; set; }
	
	public Car(string manufacturer, string model)
	{
		Manufacturer = manufacturer;
		Model = model;
	}
	
	public void Start()
	{
		if(!HasBatteryPower())
		{
			Console.WriteLine("The car can't start");
			Return;
		}
		
		if(!HasFuel())
		{
			Console.WriteLine("The car can't start");
			Return;
		}
		
		if(!CallInjector())
		{
			Console.WriteLine("The car can't start");
			Return;
		}
		
		if(!TurnOnSparkPlug())
		{
			Console.WriteLine("The car can't start");
			Return;
		}
		
		if(!StartMotor())
		{
			Console.WriteLine("The car can't start");
			Return;
		}
		
		Console.WriteLine("The car just started !");
	}
	
	private bool HasBatteryPower()
	{
	}
	
	private bool HasFuel()
	{
	}
	
	private bool CallInjector()
	{
	}
	
	private bool TurnOnSparkPlug()
	{
	}
	
	private bool StartMotor()
	{
	}
}

  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
	  Car aventador = new Car("Lamborghini", "Aventador", 8);
	  aventador.Start();
 
      // Wait for user
      Console.ReadKey();
    }
  }

When to use it ?

When for some reason you prefer keep the complexity of a system secret.

Flyweight

Wikipedia says :

A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory.

In plain words, use sharing to minimize memory usage and support a large numbers of fine-grained objects efficiently.

Real world example :

The canonical example of the flyweight pattern is the text editor. Image an english text editor without numbers or any special character, you have just 26 characters, but you can use them a multiple times. If you open a book text file, you will have tens of thousands characters, but same 26 ones. So, what do you do ? Are you create a new complete object for each of thems, knowing that you will have thousands of times the same characters ? Or you create one instance for each of the 26 characters, and you use it when you need ? The second option is called a flyweight pattern, about sharing resources.

Programmatic example :


public abstract class Letter
{
	protected char symbol;
	protected int htmlNumber;
	
	public abstract void Display(int idx);
}

public sealed class LetterA : Letter
{
	public LetterA()
	{
		symbol = 'A';
		htmlNumber = 97;
	}
	
	public override void Display(int idx) => Console.WriteLine($"Document contains the character '{symbol}' at the position {idx}");
}

public sealed class LetterB : Letter
{
	public LetterB()
	{
		symbol = 'B';
		htmlNumber = 98;
	}
	
	public override void Display(int idx) => Console.WriteLine($"Document contains the character '{symbol}' at the position {idx}");
}

// C, D, E, ...

public sealed class LetterZ : Letter
{
	public LetterZ()
	{
		symbol = 'Z';
		htmlNumber = 122;
	}
	
	public override void Display(int idx) => Console.WriteLine($"Document contains the character '{symbol}' at the position {idx}");
}

public class LetterFactory
{
	private Dictionary<char, Letter> _instances = new Dictionary<char, Letter>();
	
	public Letter GetLetter(char key)
	{
		Letter ret = null;
		
		if(_instances.ContainsKey(key))
			ret = _instances[key];
		else
		{
			switch(key)
			{
				case 'A':
					ret = new LetterA();
					break;
				case 'B':
					ret = new LetterB();
					break;
				// C, D, E, ...
				case 'Z':
					ret = new LetterZ();
					break;
				default:
					throw new ArgumentOutOfRangeException();
			}
		}
		
		return ret;
	}
}

  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
	  string documentString = "THISISMYTEXT";
	  char[] docChars = documentString.ToCharArray();
	  
	  LetterFactory factory = new LetterFactory();
	  
	  int docPosition = 0;
	  
	  foreach(char c in docChars)
	  {
		docPosition++;
		Letter l = factory.GetLetter(c);
		l.Display(docPosition);
	  }
 
      // Wait for user
      Console.ReadKey();
    }
  }

When to use it ?

When you have a few light objects but used a multiple times.

Proxy

Wikipedia says :

A proxy, in its most general form, is a class functioning as an interface to something else. A proxy is a wrapper or agent object that is being called by the client to access the real serving object behind the scenes. Use of the proxy can simply be forwarding to the real object, or can provide additional logic. In the proxy extra functionality can be provided, for example caching when operations on the real object are resource intensive, or checking preconditions before operations on the real object are invoked.

In plain words, a proxy provides a surrogate or placeholder for another object to control access to it.

Real world example :

Have you ever try to watch a parent restricted channel on the TV when you were a child ? This is a perfect proxy example. All the TV channels have things in common but when you want to watch it, you pass by a proxy who check if you have the right to watch it, adding some access logic to the channel that the channel itself doesn't know.

Placeholder programmatic example (add some behavior to access) :


public interface ITVChannel
{
	void Watch();
	int GetNumber();
}

public class TVChannel : ITVChannel
{
	public int Number { get; set; }
	public string Name { get; set; }
	public bool IsParentRestrictedAccess { get; set; }
	
	public TVChannel(int number, string name, bool restricted){
		Number =  number;
		Name = name;
		IsParentRestrictedAccess = restricted;
	}
	
	public void Watch() => Console.WriteLine("You are watching " + Name);
	
	public int GetNumber() => Number;
}

public class TVChannelProxy
{
	private ITVChannel _channel;
	
	public TVChannelProxy(ITVChannel channel)
	{
		_channel = channel;
	}
	
	public void Watch(string password)
	{
		if(!_channel.IsParentRestrictedAccess)
		{
			_channel.Watch();
			return;
		}
		
		if(string.IsNullOrWhiteSpace(password))
		{
			Console.WriteLine("This channel has a restricted access. Please provide a password.");
			return;
		}
		
		if(password != "thepasswordstoredinsomeconstant")
		{
			Console.WriteLine("This channel has a restricted access. Please provide the good password.");
			return;
		}
		
		_channel.Watch();
	}
}

public class TVChannelsProxy
{
	private Dictionary<int, TVChannelProxy> _channels = new Dictionary<int, TVChannelProxy>();
	
	public TVChannelsProxy()
	{}
	
	public void AddChannel(ITVChannel channel)
	{
		if(_channels == null)
			_channels = new Dictionary<int, ITVChannel>();
			
		if(_channels.ContainsKey(channel.GetNumber()))
			return;
			
		_channels.Add(channel.GetNumber(), new TVChannelProxy(channel));
	}
	
	public void Watch(int channelNumber, string password)
	{
		if(_channels == null)
		{
			Console.WriteLine("This proxy doesn't handle this channel");
			return;
		}
		
		if(!_channels.ContainsKey(channelNumber))
		{
			Console.WriteLine("This proxy doesn't handle this channel");
			return;
		}
		
		TVChannelProxy channelProxy = _channels[channelNumber];
		channelProxy.Watch(password);
	}
}

  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
	  ITVChannel arte = new TVChannel(7, "Arte", false);
	  ITVChannel france5 = new TVChannel(5, "France 5", false);
	  ITVChannel violentSportChannel = new TVChannel(32, "Violent Sports", true);
	  
	  TVChannelsProxy channelProxy = new TVChannelProxy();
	  channelProxy.AddChannel(arte);
	  channelProxy.AddChannel(france5);
	  channelProxy.AddChannel(violentSportChannel);
	  
	  channelProxy.Watch(arte.GetNumber(), null);
	  channelProxy.Watch(violentSportChannel.GetNumber(), null);
	  channelProxy.Watch(violentSportChannel.GetNumber(), "thepasswordstoredinsomeconstant");
 
      // Wait for user
      Console.ReadKey();
    }
  }

Surrogate programmatic example (just control access) :


public interface ISomeAPI
{
	string GetText(string id);
}

public class SomeAPI : ISomeAPI
{
	public string GetText(string id) => "this is some text, " + id;
}

public class APIProxy : ISomeAPI
{
	private SomeAPI _someAPI = new SomeAPI();
	
	public string GetText(string id) => _someAPI.GetText(id);
} 

  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
	  APIProxy apiProxy = new APIProxy();
	  
	  console.WriteLine(apiProxy.GetText("a"));
	  console.WriteLine(apiProxy.GetText("B"));
	  console.WriteLine(apiProxy.GetText("c"));
 
      // Wait for user
      Console.ReadKey();
    }
  }

When to use it ?

When you want to control access to an object.

Behavioral Design Patterns

A behavioral design pattern is about the assignments of responsabilies between the objects.

Wikipedia says :

In software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication.

Chain of Responsibility

Wikipedia says :

In object-oriented design, the Chain of Responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain.

In plain words, the Chain of Responsibility pattern handles a chain of objects. It's handle a request from one and manage the chain from object to object until the response.

Real world example :

Imagine you apply to a job in the military forces, you have to respond to some criterias like, have passed with success the test, have passed an interview with a recruiter and have an empty criminal record. If you apply to a job, a person will vérify all of this criterias and will call the good interlocutor for each of them (police to check the criminnal record, the recruiter for his opinion after the interview and the administration to get the result of the test).

Programmatic example :


public abstract class ApplicationManager
{
	protected ApplicationManager Successor;
	
	public void SetSuccessor(ApplicationManager successor)
	{
		Successor = successor;
	}
	
	public abstract void ProcessRequest(string personName);
}

public class TestResultApplicationManager : ApplicationManager
{
	public override void ProcessRequest(string personName)
	{
		if(!HasPassed(personName))
		{
			Console.WriteLine("You need to pass the test");
			Return;
		}
		
		if(!IsApprouved(personName))
		{
			Console.WriteLine("Rejected");
			Return;
		}
		
		Console.WriteLine("The write test application department approved the application of " + personName);
		
		if(Successor != null)
			Successor.ProcessRequest(personName);
	}
	
	private bool HasPassed(string personName)
	{
		// Check if this person has passed the test
	}
	
	private bool IsApprouved(string personName)
	{
		// Check if this person succeed or failed
	}
}

public class InterviewApplicationManager : ApplicationManager
{
	public override void ProcessRequest(string personName)
	{
		if(!HasPassed(personName))
		{
			Console.WriteLine("You need to pass the interview");
			Return;
		}
		
		if(!IsApprouved(personName))
		{
			Console.WriteLine("Rejected");
			Return;
		}
		
		Console.WriteLine("The interview application department approved the application of " + personName);
		
		if(Successor != null)
			Successor.ProcessRequest(personName);
	}
	
	private bool HasPassed(string personName)
	{
		// Check if this person has passed an interview
	}
	
	private bool IsApprouved(string personName)
	{
		// Check if the recruiter approved the applicant or not
	}
}

public class PhysicalTestApplicationManager : ApplicationManager
{
	public override void ProcessRequest(string personName)
	{
		if(!HasPassed(personName))
		{
			Console.WriteLine("You need to pass the physical test");
			Return;
		}
		
		if(!IsApprouved(personName))
		{
			Console.WriteLine("Rejected");
			Return;
		}
		
		Console.WriteLine("The physical test application department approved the application of " + personName);
		
		if(Successor != null)
			Successor.ProcessRequest(personName);
	}
	
	private bool HasPassed(string personName)
	{
		// Check if this person has passed an interview
	}
	
	private bool IsApprouved(string personName)
	{
		// Check if the recruiter approved the applicant or not
	}
}

public class PoliceApplicationManager : ApplicationManager
{
	public override void ProcessRequest(string personName)
	{
		if(HasCriminalRecord(personName))
		{
			Console.WriteLine("Rejected");
			Return;
		}
		
		Console.WriteLine("The Police approved the application of " + personName);
		
		if(Successor != null)
			Successor.ProcessRequest(personName);
	}
	
	private bool HasCriminalRecord(string personName)
	{
		// Check if the applicant has a criminal record
	}
}

  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
	  ApplicationManager police = new PoliceApplicationManager();
	  ApplicationManager test = new TestApplicationManager();
	  ApplicationManager pysicalTest = new PhysicalTestApplicationManager();
	  ApplicationManager interview = new InterviewApplicationManager();
	  
	  police.SetSuccessor(test);
	  test.SetSuccessor(pysicalTest);
	  pysicalTest.SetSuccessor(interview);
	  
	  string personName = "Adrien Torris";
	  police.ProcessRequest(personName);
 
      // Wait for user
      Console.ReadKey();
    }
  }

Command

Wikipedia says :

In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time. This information includes the method name, the object that owns the method and values for the method parameters.

In plain words, a command pattern encapsulates a method call as an object.

Real world example :

A very common example is you (i.e. Client) switching on (i.e. Command) the television (i.e. Receiver) using a remote control (Invoker).

Programmatic example :


// Receiver
public class Television
{
	public void TurnOn() => Console.WriteLine("You are watching TV");
	
	public void TurnOff() => Console.WriteLine("Get out ! I'm sleeping ...");
}

// Command
public interface ICommand
{
	void Execute();
	void Undo();
	void Redo();
}

// Command
public class TurnOn : ICommand
{
	private Television _television;
	
	public TurnOn(Television t)
	{
		_television = t;
	}
	
	public void Execute() => _television.TurnOn();
	
	public void Undo() => _television.TurnOff();
	
	public void Redo() => Execute();
}

// Command
public class TurnOff : ICommand
{
	private Television _television;
	
	public TurnOn(Television t)
	{
		_television = t;
	}
	
	public void Execute() => _television.TurnOff();
	
	public void Undo() => _television.TurnOn();
	
	public void Redo() => Execute();
}

// Invoker
public class RemoteControl
{
	public void Submit(ICommand cmd) => cmd.Execute();
}

  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
	  Television television = new Television();
	  
	  ICommand turnOnCommand = new TurnOn(television);
	  ICommand turnOffCommand = new TurnOff(television);
	  
	  RemoteControl remoteControl = new RemoteControl();
	  
	  remoteControl.Submit(turnOnCommand); // Will print: You are watching TV
	  remoteControl.Submit(turnOffCommand); // Will print: Get out ! I'm sleeping ...
 
      // Wait for user
      Console.ReadKey();
    }
  }

Iterator

Wikipedia says :

In object-oriented programming, the iterator pattern is a design pattern in which an iterator is used to traverse a container and access the container's elements. The iterator pattern decouples algorithms from containers; in some cases, algorithms are necessarily container-specific and thus cannot be decoupled.

In plain words, an iterator provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

Real world example :

A television with a "next" and a "previous" button is a good example. You can click on "next" and "previous" to iterate on all the channels.

Programmatic example :


public class Channel
{
	public string Name {get;}
	
	public Channel(string name){
		Name = name;
	}
}

public class Television
{
	private IList _channels;
	
	private int _currentChannelIndex;
	
	public Television()
	{
		_channels = new List();
		_currentChannelIndex = 0;
	}
	
	public void AddChannel(Channel c) => _channels.Add(c);
	
	public void Next() => _currentChannelIndex += 1;
	
	public void Rewind() => _currentChannelIndex -= 1;
	
	public Channel GetChannel() => _channels[_currentChannelIndex];
}
February 26, 2017
  • Design Patterns
  • Design Pattern
  • Simple Factory
  • Factory Method
  • Abstract Factory