Category Archives: Design patterns

Design patterns – Visitor

Visitor is a behavioural pattern. It is used to perform some action on group of similar object without editing these objects. Updating logic is in visitor, rather than implemented in visited objects.
Imagine the case where you have many employees and you want to update theirs salary. We can use Visitor pattern for it. Salary update logic can be implemented in SalaryUpdatingVisitor and then any employee don’t know this logic.

This is our Employee class. Using it’s properties Visitor can update the Salary.

    interface IEmployee
    {
        double Salary { get; set; }
        int ExperienceLevel { get; set; }
        int SkillsLevel { get; set; }

        /// <summary>
        /// Starts visitor's work.
        /// </summary>
        /// <param name="v"></param>
        void Accept(IEmployeeVisitor v);
    }
	
    class Employee : IEmployee
    {
        public Employee(string firstName, string lastName, double salary, int experience, int skills)
        {
            FirstName = firstName;
            LastName = lastName;
            Salary = salary;
            ExperienceLevel = experience;
            SkillsLevel = skills;
        }

        public string FirstName { get; set; }
        public string LastName { get; set; }

        public double Salary { get; set; }
        public int ExperienceLevel { get; set; }
        public int SkillsLevel { get; set; }

        public void Accept(IEmployeeVisitor v)
        {
            Console.WriteLine($"{LastName} accepted {v.GetType().Name}.");
            v.Visit(this);
        }

    }

Our visitor – it’s implementation constains only one method Visit which takes as a parameter IEmployee.

    interface IEmployeeVisitor
    {
        /// <summary>
        /// Contains logic to perform on visited object.
        /// </summary>
        /// <param name="e"></param>
        void Visit(IEmployee e);
    }
	
	class SalaryUpdatingVisitor : IEmployeeVisitor
    {
        public void Visit(IEmployee e)
        {
            if (e.ExperienceLevel * e.SkillsLevel <= 10)
            {
                Console.WriteLine("Cheesy worker, no pay rise.");
                return;
            }
            else if (e.ExperienceLevel * e.SkillsLevel <= 20)
            {
                Console.WriteLine("Small payrise applied.");
                e.Salary += 100;
            }
            else
            {
                Console.WriteLine("Nice payrise applied.");
                e.Salary += 500;
            }
        }
    }

And now the usage. Let’s create a few employees and update theirs salaries using visitor.

        public static void VisitorUsage()
        {
            var visitor = new SalaryUpdatingVisitor();
            var employees = new List<IEmployee>();
            employees.Add(new Employee("John", "Smith", 2000, 10, 5));
            employees.Add(new Employee("Alice", "White", 1500, 2, 6));

            foreach (var e in employees)
            {
                e.Accept(visitor);
            }
        }
Advertisements

Bridge – design patterns

Bridge is a structural pattern which decouples abstraction from implementation. Uses composition rather than inheritance.
Imagine you have two shapes: circle and triangle. They can be colored with two colors: black and red. Imagine you want to implement simple inheritance. Base class will be shape. Circle and triangle inherits from shape. RedCircle, BlackCircle, RedTriangle, BlackTriangle inherit from circle and triangle.
Imagine you would have 10 different shapes and 10 different colors. You would end up with 100 classes (RedRectangle, BlueEllpse, PinkSquare, etc.).
To avoid such situation we would implement bridge. We can decouple two different things – shapes and colors.
We can implement concrete Circle and Triangle which base on abstract Shape class. On the other hand we can implement RedColor and BlackColor on IColor interface. We pass instance of color in shape constructor.
See example below.

Our colors.

namespace DesignPatterns.Bridge
{
    /// <summary>
    /// Interface for colors.
    /// </summary>
    interface IColor
    {
        void Apply();
    }
}
[/sourcecode language="csharp"]


using System;

namespace DesignPatterns.Bridge
{
    /// <summary>
    /// Represents red color
    /// </summary>
    class RedColor : IColor
    {
        public void Apply()
        {
            Console.WriteLine("Filling with red.");
        }
    }
}


using System;

namespace DesignPatterns.Bridge
{

    /// <summary>
    /// Represents black color.
    /// </summary>
    class BlackColor : IColor
    {
        public void Apply()
        {
            Console.WriteLine("Filling with black.");
        }
    }
}

Our shapes. Reference to IColor is passed in constructor. It is used in DrawColored method.

namespace DesignPatterns.Bridge
{
    /// <summary>
    /// Interface for shapes. Handles reference to color.
    /// </summary>
    abstract class Shape
    {
        protected IColor _color;

        /// <summary>
        /// Constructor with passed color.
        /// </summary>
        /// <param name="color"></param>
        public Shape(IColor color)
        {
            _color = color;
        }

        /// <summary>
        /// Draws shape using color given in constructor.
        /// </summary>
        public abstract void DrawColored();
    }
}
using System;
using System.Drawing;

namespace DesignPatterns.Bridge
{
    /// <summary>
    /// Circle - concrete implementation of shape
    /// </summary>
    class Circle : Shape
    {
        public Circle(IColor color, Point center, int radius) : base(color)
        {
            Center = center;
            Radius = radius;
        }

        public Point Center { get; private set; }
        public int Radius { get; private set; }

        public override void DrawColored()
        {
            _color.Apply();
            Console.WriteLine($"Drawing circle with applied color.");
        }
    }
}


using System;
using System.Drawing;

namespace DesignPatterns.Bridge
{
    /// <summary>
    /// Triangle - concrete implementation of shape
    /// </summary>
    class Triangle : Shape
    {
        public Triangle(IColor color, Point a, Point b, Point c) : base(color)
        {
            A = a;
            B = b;
            C = c;
        }

        public Point A { get; private set; }
        public Point B { get; private set; }
        public Point C { get; private set; }

        public override void DrawColored()
        {
            _color.Apply();
            Console.WriteLine($"Drawing triangle with applied color");
        }
    }
}

Usage of the bridge. Three shapes are created with two different colors.

        public static void BridgeUsage()
        {
            var redCircle = new Bridge.Circle(new Bridge.RedColor(), new System.Drawing.Point(0, 0), 10);
            var blackCircle = new Bridge.Circle(new Bridge.BlackColor(), new System.Drawing.Point(0, 0), 10);
            var redTriangle = new Bridge.Triangle(new Bridge.RedColor(), new System.Drawing.Point(10, 0), new System.Drawing.Point(0, 10), new System.Drawing.Point(5, 5));

            redCircle.DrawColored();
            blackCircle.DrawColored();
            redTriangle.DrawColored();
        }

Design patterns – Proxy

Proxy it’s a structural design pattern used to create additional layer to access an object. Imagine you have an object with time-consuming initialization and you want to do this initialization only when this object is really needed. In such case you can have proxy object to decide when to initialize.
Proxy class should implement the same interface as ‘real’ class and have a reference to ‘real’ object.

In our example we have SumOperation class. Calculate method in this class is time consuming. We would like to cache it, to not execute it always when somebody calls to save time. SumOperationProxy class is implemented therefore. Both of them implement IOperation interface.

Our ‘real’ class with the interface.

    /// <summary>
    /// Interface for 'real' class and proxy class
    /// </summary>
    interface IOperation
    {

        string GetName();
        int Parameter { get; }
        int Calculate();
    }
	
    /// <summary>
    ///'Real' class with time consuming Calculate method.
    /// </summary>
    class SumOperation : IOperation
    {
        public SumOperation(int i)
        {
            Parameter = i;
        }

        public int Parameter { get; private set; }

        public int Calculate()
        {
            int result = 0;
            for (int j = 1; j <= Parameter; j++)
            {
                result += j;
                System.Threading.Thread.Sleep(1000);
            }
            return result;
        }

        public string GetName()
        {
            return $"Sum operation for {Parameter}.";
        }
    }

Our proxy class.

    /// <summary>
    /// Proxy class to cache time consuming method in 'real' class.
    /// Implements the same interface like 'real' class.
    /// </summary>
    class SumOperationProxy : IOperation
    {
        SumOperation _operation = null;
        int _result = 0;

        public SumOperationProxy(int i)
        {
            _operation = new SumOperation(i);
        }

        public int Parameter
        {
            get
            {
                return _operation.Parameter;
            }
        }

        public int Calculate()
        {
            if (_result == 0)
                _result = _operation.Calculate();

            return _result;
        }

        public string GetName()
        {
            return _operation.GetName();
        }
    }

Proxy usage. Notice that Calculate call for the first time takes much time, but for the second time it is executed fast.

        public static void ProxyUsage()
        {
            //instantiates proxy object quickly
            var myOperationProxy = new SumOperationProxy(5);
            Console.WriteLine(myOperationProxy.GetName());

            //heavy operation performed for a long time
            Console.WriteLine(myOperationProxy.Calculate());

            //heavy operation performed quickly as was cached by proxy class
            Console.WriteLine(myOperationProxy.Calculate());
        }

Design patterns – Adapter

Adapter is a structural pattern. It is used when an existing class is useful, but do not fully implement required interface. This existing class is called adaptee. The required interface is called target. Class which implements target interface and has got reference to adaptee is an adapter.

Imagine we try to write any 2D graphics software. We created an interface IShape2D and already have implemented Triangle class. We need another class – Rectangle. It is already implemented in System.Drawing namespace, but doesn’t fully meet our requirements. We can try to adapt it.

Out interface and Triangle class.

    /// <summary>
    /// Target interface to be implemented by targets.
    /// </summary>
    interface IShape2D
    {
        double CalculateArea();
    }
	
    /// <summary>
    /// Equilateral triangle. 
    /// Out class which implements target interface.
    /// </summary>
    class Triangle : IShape2D
    {
        private int _sideLength;

        public Triangle(int sideLength)
        {
            _sideLength = sideLength;
        }

        public double CalculateArea()
        {
            return Math.Pow(_sideLength, 2) * Math.Sqrt(3) / 4;
        }
    }

Adapted rectangle class.

    /// <summary>
    /// Adapter class.
    /// Contains reference to System.Windows.Rectangle (adaptee) and implements IShape2D interface (target)
    /// </summary>
    class Rectangle : IShape2D
    {
        private System.Drawing.Rectangle _adapteeRectangle;

        public Rectangle(int x, int y, int width, int height)
        {
            _adapteeRectangle = new System.Drawing.Rectangle(x, y, width, height);
        }

        public double CalculateArea()
        {
            return _adapteeRectangle.Width * _adapteeRectangle.Height;
        }
    }
        public static void AdapterUsage()
        {
            var shapes = new List<IShape2D>();
            shapes.Add(new Triangle(4));
            shapes.Add(new Adapter.Rectangle(0, 0, 10, 4));

            foreach (var s in shapes)
            {
                Console.WriteLine(s.CalculateArea());
            }
        }

Design patterns – Strategy

Strategy pattern is a behavioral pattern. It defines group of algorithms which do the same thing, but different way. It keeps the algorithm independent from it’s caller.
Imagine you want to serialize data in different ways: to XML and to binary data.

Our strategies with interface.

    interface ISerializationStrategy
    {
        string Serialize(object x);
    }
	
    /// <summary>
    /// Serialization strategy to serialize object to xml
    /// </summary>
    class XmlSerializationStrategy : ISerializationStrategy
    {
        public string Serialize(object x)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(object));
            using (var writer = new StringWriter())
            {
                serializer.Serialize(writer, x);
                return writer.ToString();
            }
        }
    }
	
    /// <summary>
    /// Serialization strategy to serialize object to binary
    /// </summary>
    class BinarySerializationStrategy : ISerializationStrategy
    {
        public string Serialize(object x)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            using (var stream = new MemoryStream())
            using (var reader = new StreamReader(stream))
            {
                formatter.Serialize(stream, x);
                stream.Position = 0;
                return reader.ReadToEnd();
            }
        }
    }

Our strategy context which uses strategies.

    /// <summary>
    /// Context which uses one of serialization strategy.
    /// </summary>
    class SerializationContext
    {
        private ISerializationStrategy _strategy;

        public SerializationContext(ISerializationStrategy strategy)
        {
            _strategy = strategy;
        }

        public void PerformSerialization(object x)
        {
            Console.WriteLine(_strategy.Serialize(x));
        }
    }

Usage example:

        public static void StrategyUsage()
        {
            var strategyXml = new XmlSerializationStrategy();
            var strategyBinary = new BinarySerializationStrategy();

            var contextA = new SerializationContext(strategyXml);
            var contextB = new SerializationContext(strategyBinary);

            contextA.PerformSerialization("Test");
            contextB.PerformSerialization("Test");
        }

Design patterns – Decorator

Decorator pattern (also known as wrapper) is structural pattern. It allows you to attach some funcionality to existing object. It’s more flexible alternative to subclassing as you can attach functionality dynamically in runtime.
Imagine we have class which prints sum of two values.
We can imagine a decorator which adds currency sign or other chars to the printed value.
The class which can be decorated is called concrete component.
Both composite and decorator implement the same interface (or inherit the same base class). Decorator has got a reference to the component.

Our concrete composite with interface:

    /// <summary>
    /// Interface for all components and decorators
    /// </summary>
    interface IValuePrinterComponent
    {
        void Print();
    }
	
    /// <summary>
    /// Component to print sum of two values.
    /// It can be decorated by decorator.
    /// </summary>
    class SumPrinterComponent : IValuePrinterComponent
    {
        protected int _sum;
        public SumPrinterComponent(int a, int b)
        {
            _sum = a + b;
        }

        public virtual void Print()
        {
            Console.WriteLine(_sum);
        }
    }

Our two simple decorators:

    enum Severity
    {
        Minor,
        Major,
        Critical
    }

    /// <summary>
    /// Decorator to decorate printed value with warning sign
    /// </summary>
    class ValuePrinterWarningDecorator : IValuePrinterComponent
    {
        protected IValuePrinterComponent _component;
        private Severity _serverity;

        public ValuePrinterWarningDecorator(IValuePrinterComponent component, Severity severity)
        {
            _component = component;
            _serverity = severity;
        }

        public virtual void Print()
        {
            DecoratePrint();
            _component.Print();
        }

        private void DecoratePrint()
        {
            if (_serverity == Severity.Critical)
                Console.Write("!!!");
            else if (_serverity == Severity.Major)
                Console.Write("!!");
            else
                Console.Write("!");

        }
    }
	
    enum Currency
    {
        Pound,
        Dollar,
    }

    /// <summary>
    /// Decorator to decorate printed value with currency sign
    /// </summary>
    class ValuePrinterCurrencyDecorator : IValuePrinterComponent
    {
        protected IValuePrinterComponent _component;
        private Currency _currency;

        public ValuePrinterCurrencyDecorator(IValuePrinterComponent component, Currency currency)
        {
            _component = component;
            _currency = currency;
        }

        public virtual void Print()
        {
            DecoratePrint();
            _component.Print();
        }

        private void DecoratePrint()
        {
            if (_currency == Currency.Dollar)
                Console.Write("$");
            else if (_currency == Currency.Pound)
                Console.Write("£");

        }
    }

Usage example:

        private static void DecoratorUsage()
        {
            //using printer without any decorator
            var notDecoratedPrinter = new SumPrinterComponent(2, 3);
            notDecoratedPrinter.Print();

            //using printer with currency decorator only
            var currencyDecoratedPrinter = new ValuePrinterCurrencyDecorator(notDecoratedPrinter, Currency.Pound);
            currencyDecoratedPrinter.Print();

            //using printer with warning decorator only
            var warningDecoratedPrinter = new ValuePrinterWarningDecorator(notDecoratedPrinter, Severity.Critical);
            warningDecoratedPrinter.Print();

            //using printer with both decorators
            IValuePrinterComponent fullDecoratedPrinter = new ValuePrinterCurrencyDecorator(notDecoratedPrinter, Currency.Dollar);
            fullDecoratedPrinter = new ValuePrinterWarningDecorator(fullDecoratedPrinter, Severity.Minor);
            fullDecoratedPrinter.Print();
        }

Design patterns – Builder

Builder pattern should be used when you try to create similar complex objects. These objects are created step by step. You want to separate creation logic from objects representation.

Participants are:
Product – objects which are being created (Bungalow and BlockOfFlats in our example).
Builders – objects which create products step by step (BungalowBuilder, BlockOfFlatsBuilder). They are based on HouseBuilder class.
HouseDirector – object which uses different builders (implementing the same interface) to get different products.

Our products with base class:

    /// <summary>
    /// Base class for created (by builders) houses.
    /// </summary>
    class HouseBase
    {
        public HouseBase() { }

        public string Basement { get; set; }
        public string MainPart { get; set; }
        public string Roof { get; set; }

        /// <summary>
        /// Describes created house.
        /// </summary>
        /// <returns></returns>
        public string DescribeYourself()
        {
            var sb = new StringBuilder();
            sb.Append("I have: ");
            sb.Append(Environment.NewLine);
            sb.Append(Basement);
            sb.Append(Environment.NewLine);
            sb.Append(MainPart);
            sb.Append(Environment.NewLine);
            sb.Append(Roof);
            return sb.ToString();
        }
    }
	
    /// <summary>
    /// Represents block of flats (type of a house).
    /// </summary>
    class BlockOfFlats : HouseBase
    {
        public int NumberOfFloors
        {
            get { return 15; }
        }

        public int NumberOfFlats
        {
            get { return NumberOfFlats * 10; }
        }
    }
	
    /// <summary>
    /// Represents bungalow (type of a house).
    /// </summary>
    class Bungalow : HouseBase
    {
        public void LightTheFireplace()
        {
            throw new NotImplementedException();
        }
    }

Our concrete builders with base class:

    /// <summary>
    /// Abstract class as a base for concrete house builders.
    /// Contains abstract methods which should be implemented separately in each type of concrete builder.
    /// </summary>
    abstract class HouseBuilder
    {
        protected HouseBase _house;

        public abstract void CreateBasement();
        public abstract void CreateWalls();
        public abstract void CreateRoof();

        public HouseBase GetHouse()
        {
            return _house;
        }
    }
	
    /// <summary>
    /// Represents a builder which can create a block of flats.
    /// </summary>
    class BlockOfFlatsBuilder : HouseBuilder
    {
        public BlockOfFlatsBuilder()
        {
            _house = new BlockOfFlats();
        }

        public override void CreateBasement()
        {
            _house.Basement = "deep basement with many rooms";
        }

        public override void CreateRoof()
        {
            _house.Roof = "flat roof high above the ground";
        }

        public override void CreateWalls()
        {
            _house.MainPart = "15 floors";
        }
    }
	
    /// <summary>
    /// Represents a builder which can create a bungalow.
    /// </summary>
    class BungalowBuilder : HouseBuilder
    {
        public BungalowBuilder()
        {
            _house = new Bungalow();
        }

        public override void CreateBasement()
        {
            _house.Basement = "no basement";
        }

        public override void CreateRoof()
        {
            _house.Roof = "ridge roof with small chimney";
        }

        public override void CreateWalls()
        {
            _house.MainPart = "single floor";
        }
    }

Our director:

    /// <summary>
    /// Director uses builder to construct a house.
    /// </summary>
    class HouseDirector
    {
        /// <summary>
        /// Constructs appropriate house step by step basing on logic in builder.
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public HouseBase Construct(HouseBuilder builder)
        {
            builder.CreateBasement();
            builder.CreateWalls();
            builder.CreateRoof();
            return builder.GetHouse();
        }
    }

The sample usage:

        private static void BuilderUsage()
        {
            var houseDirector = new HouseDirector();

            var bungalowBuilder = new BungalowBuilder();
            var house1 = houseDirector.Construct(bungalowBuilder);
            Console.WriteLine(house1.DescribeYourself());

            var blockOfFlatsBuilder = new BlockOfFlatsBuilder();
            var house2 = houseDirector.Construct(blockOfFlatsBuilder);
            Console.WriteLine(house2.DescribeYourself());

        }