Wednesday, November 27, 2013

Refactoring to Command design pattern

Hello

Example inspired by Russian language explanation of [DesignPattern] Command
Native Russian speakers can see the good video on YouTube

So, the example is about remote control for home stuff, like TV, MP3 player, Lights etc. We assume, that these devices have only on/off states

So, lets design RC for Light, MP3 and video electrical devices

RC will be looks like box with 6 buttons:

  • Light on
  • Light off
  • MP3 on
  • MP3 off
  • Video on
  • Video off
Lets code it!


namespace RemoteControlDP
{
    public class RemoteControl
    {
        public void DrawMenu()
        {
            Console.WriteLine("Select operation:");
            Console.WriteLine("1\t on light");
            Console.WriteLine("1 off\t off light");
            Console.WriteLine("2\t on tv");
            Console.WriteLine("2 off\t off tv");
            Console.WriteLine("3\t on mp3");
            Console.WriteLine("3 off\t off mp3");
        }

        public enum ProductState { On, Off }

        public void PerformAction()
        {
            string userSelected = Console.ReadLine();

            switch (userSelected)
            {
                case "1":
                    LightOn();
                    break;
                case "1 off":
                    LightOff();
                    break;
                case "2":
                    TVOn();
                    break;
                case "2 off":
                    TVOff();
                    break;
                case "3":
                    MP3On();
                    break;
                case "3 off":
                    MP3Off();
                    break;
            }
        }

        private static void MP3Off()
        {
            Console.WriteLine("MP3 is off");
        }

        private static void MP3On()
        {
            Console.WriteLine("MP3 is on");
        }

        private static void TVOff()
        {
            Console.WriteLine("TV is off");
        }

        private static void TVOn()
        {
            Console.WriteLine("TV is on");
        }

        private static void LightOff()
        {
            Console.WriteLine("Light is off");
        }

        private static void LightOn()
        {
            Console.WriteLine("Light is on");
        }
    }
}

Client code:
namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            RemoteControl remote = new RemoteControl();
            string userInput = string.Empty;

            do
            {
                remote.DrawMenu();
                remote.PerformAction();

                Console.WriteLine("To continue select y");
                userInput = Console.ReadLine();
            }
            while (userInput.Equals("y"));
        }
    }
}

UML class Diagram lol:


Very good, until comes one of 3 inevitable things: Change Requirements

Client wish command on Fan!
So, lets rock. Class RemoteControl gonna be opened, changed, added etc. Bad smell!
After client wish add Radio, printer, PC etc.

Lets encapsulate changes and use some smart thing, was invented by 4 smart humans. Lets refactor to Command Design Pattern : "Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations".

Big picture: i wish create structure of classes and its relationships, so i can create programs and assign to buttons in real-time. Looks fine! It is like programmable Logitech remote control:
which can be programmed in real time and commands will be assigned to buttons! A little difference, SW we do in our self, no need to pay for it :-)

First part: create commands which do On operation (Off operation will be described in second part):

ICommand interface. There only one method:
namespace RemoteControlDP
{
    public interface ICommand
    {
        void Execute();
    }
}

Light, MP3 and Video implementations. Each implementation also have overriding of ToString. We will see use of it in RemoteControl class.

using System;

namespace RemoteControlDP
{
    public class LightCommand : ICommand
    {
        public void Execute()
        {
            Console.WriteLine("Light is on");
        }

        public override string ToString()
        {
            return "on Light";
        }
    }
}

using System;

namespace RemoteControlDP
{
    public class MP3Command : ICommand
    {
        public void Execute()
        {
            Console.WriteLine("MP3 is on");
        }

        public override string ToString()
        {
            return "on MP3";
        }
    }
}

using System;

namespace RemoteControlDP
{
    public class TVCommand : ICommand
    {
        public void Execute()
        {
            Console.WriteLine("TV is on");
        }

        public override string ToString()
        {
            return "on TV";
        }
    }
}

RemoteControl refactored:
using System;
using System.Collections.Generic;

namespace RemoteControlDP
{
    public class RemoteControl
    {
        Dictionary<string, ICommand> _commands;

        public RemoteControl()
        {
            _commands = new Dictionary<string, ICommand>();
        }

        public void SetCommand(string button, ICommand cmd)
        {
            _commands[button] = cmd;
        }

        public void DrawMenu()
        {
            Console.WriteLine("Select operation:");

            foreach (String btn in _commands.Keys)
            {
                Console.WriteLine("{0} \t - {1}", btn, _commands[btn].ToString());
            }
        }

        public void PerformAction()
        {
            string userSelected = Console.ReadLine() ?? String.Empty;

            if (_commands.ContainsKey(userSelected))
            {
                _commands[userSelected].Execute();
            }
        }
    }
}

RemoteControl explained:
  • Collection. There collection of assigned commands per buttons. Class have no idea about command. It is incapsulated.
  • SetCommand. Ability assign buttons to commands from outside. From client, for a true.
  • DrawMenu. There no need long list of strings, only calling to overridden ToString method in ICommand  implementations.
  • PerformAction. Just call to Execute method of ICommand  implementations.
Client slightly changed:
namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            RemoteControl remote = new RemoteControl();
            string userInput = string.Empty;
   
            remote.SetCommand("1", new LightCommand());
            remote.SetCommand("2", new TVCommand());
            remote.SetCommand("3", new MP3Command());
            
            do
            {
                remote.DrawMenu();
                remote.PerformAction();

                Console.WriteLine("To continue select y");
                userInput = Console.ReadLine();
            }
            while (userInput.Equals("y"));
        }
    }
}
There using of assign command to buttons in real-time.

So, if we need add Fan, we only create Fan class, implement ICommand and add it to remote, using SetCommand.

UML class diagram:


UML Sequence diagram:
Lets see GOF class diagram (taken from http://www.dofactory.com):
Client - is same as our client
Invoker - is RemoteControl
Command - is ICommand
ConcreteCommand - is Light/MP3/TV command
Receiver - will be added later

Lets continue refactoring to GOF pattern.

I wish add Receiver class. Is real implementation of devices. Its includes its state too.
My recievers called LightReceiver, MP3Receiver, TVReceiver.
namespace RemoteControlDP
{
    public enum ReceiverState { On, Off, }
}

using System;

namespace RemoteControlDP
{
    public class TVReceiver
    {
        public void TurnOn()
        {
            DeviceState = ReceiverState.On;
            Console.WriteLine("TV is {0}", DeviceState);
        }

        public ReceiverState DeviceState { get; private set; }
    }
}

using System;

namespace RemoteControlDP
{
    public class MP3Receiver
    {
        public void TurnOn()
        {
            DeviceState = ReceiverState.On;
            Console.WriteLine("MP3 is {0}", DeviceState);
        }

        public ReceiverState DeviceState { get; private set; }
    }
}

See 2 kinds of lights: Color and somple light:
using System;

namespace RemoteControlDP
{
    public abstract class LightReceiver
    {
        public virtual void TurnOn()
        {
            DeviceState = ReceiverState.On;
            Console.WriteLine("Light is {0}", DeviceState);
        }

        public ReceiverState DeviceState { get; private set; }
    }

    public class ColorLightReceiver : LightReceiver
    {
        public override void TurnOn()
        {
            base.TurnOn();
            Console.WriteLine("Red Color");
        }
    }
}

using System;

namespace RemoteControlDP
{
    public class FanReceiver
    {
        public void TurnOn()
        {
            DeviceState = ReceiverState.On;
            Console.WriteLine("Fan is {0}", DeviceState);
        }

        public ReceiverState DeviceState { get; private set; }
    }
}

Commands changed too:
This class will contain injected Recievers realisation and have method Action
Receiver for Light can be injected as different Lights implementations, so it makes system more flexible.

using System;

namespace RemoteControlDP
{
    public class FanCommand : ICommand
    {
        private FanReceiver _fan;

        public FanCommand(FanReceiver fan)
        {
            _fan = fan;
        }

        public void Execute()
        {
            _fan.TurnOn();
        }

        public override string ToString()
        {
            return "on Fan";
        }
    }
}

using System;

namespace RemoteControlDP
{
    public class LightCommand : ICommand
    {
        private LightReceiver _light;

        public LightCommand(LightReceiver light)
        {
            _light = light;
        }

        public void Execute()
        {
            _light.TurnOn();
        }

        public override string ToString()
        {
            return "on Light";
        }
    }
}

using System;

namespace RemoteControlDP
{
    public class MP3Command : ICommand
    {
        private MP3Receiver _mp3;

        public MP3Command(MP3Receiver mp3)
        {
            _mp3 = mp3;
        }

        public void Execute()
        {
            _mp3.TurnOn();
        }

        public override string ToString()
        {
            return "on MP3";
        }
    }
}

using System;

namespace RemoteControlDP
{
    public class TVCommand : ICommand
    {
        private TVReceiver _tv;

        public TVCommand(TVReceiver tv)
        {
            _tv = tv;
        }

        public void Execute()
        {
            _tv.TurnOn();
        }

        public override string ToString()
        {
            return "on TV";
        }
    }
}

Client changed too:
namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            RemoteControl remote = new RemoteControl();
            string userInput = string.Empty;
   
            remote.SetCommand("1", new LightCommand(new ColorLightReceiver()));
            remote.SetCommand("2", new TVCommand(new TVReceiver()));
            remote.SetCommand("3", new MP3Command(new MP3Receiver()));
            remote.SetCommand("4", new FanCommand(new FanReceiver()));
            
            do
            {
                remote.DrawMenu();
                remote.PerformAction();

                Console.WriteLine("To continue select y");
                userInput = Console.ReadLine();
            }
            while (userInput.Equals("y"));
        }
    }
}
You can see, Light command injected by Color light. It can be injected by other implementation of light.

Now, our design is looks like GOF design.

Class diagram:


We can stop here, but Command design pattern by GOF "...and support undoable operations."
Later i will cover it, or try it yourself.

that's it


en → ru
Expl

Monday, November 18, 2013

Tuesday, November 12, 2013

Strategy Design Pattern

Hello

There is pretty simple pattern, which make encapsulation of algorithms

Class diagrams, from different points of view.

Class Diagram

Fig 1:class diagram without associations

Fig 2: class diagram with client associations

Fig 3: class diagram with associations inside of Startegy pattern

Explanations of class diagrams from point of view of Associations:
Fig 1: Nothing to say
Fig 2: Client should know only Context class because of client instantiate it. Client should know about all implemented algorithms, because of client instantiate context with specific algorithm.
Fig 3: Inside of pattern implementation, only Context should know about IStrategy, because of Contexts instantiated with IStrategy interface.

Code is example of calculations algorithms:

namespace StrategyDP
{
    public class Calculator
    {
        private ICalculation _calc;

        public Calculator(ICalculation calc)
        {
            _calc = calc;
        }

        public double Calculate(double a, double b)
        {
            return _calc.Calculate(a, b);
        }
    }

    public interface ICalculation
    {
        double Calculate(double a, double b);
    }

    public class AddAlg : ICalculation
    {
        public double Calculate(double a, double b)
        {
            return a + b;
        }
    }

    public class MinusAlg : ICalculation
    {
        public double Calculate(double a, double b)
        {
            return a - b;
        }
    }

    public class DevAlg : ICalculation
    {
        public double Calculate(double a, double b)
        {
            return a / b;
        }
    }

    public class MulAlg : ICalculation
    {
        public double Calculate(double a, double b)
        {
            return a * b;
        }
    }
}

Using (as UniTest):
Calculator calc = new Calculator(new AddAlg());
Assert.AreEqual(calc.Calculate(6, 2), 8);
calc = new Calculator(new MinusAlg());
Assert.AreEqual(calc.Calculate(6, 2), 4);
calc = new Calculator(new DevAlg());
Assert.AreEqual(calc.Calculate(6, 2), 3);
calc = new Calculator(new MulAlg());
Assert.AreEqual(calc.Calculate(6, 2), 12);

That's all

Abstract Factory Design Pattern

Hello

Abstract Factory  Design Pattern is largest pattern from 3 factory-family patterns:

1. Simple Factory
2. Abstract Factory
3. Factory Method

I will start from implementation, using, class diagrams. After, i will put points, make comparing to other patterns in family.

Code

As implementation i use example: building Suzuki liana and Peugeot 206 by using Abstract Factory  Design Pattern:
namespace AbstractFactoryDP
{
    #region Interfaces

    public interface IEngine
    {
        int GetHorsePower();
        double GetVolume();
    }

    public interface IWheel
    {
        int GetTireWidth();
        int GetAspectRatio();
    }

    public interface IAbstractCarsFactory
    {
        IEngine FactoryEngine();
        IWheel FactoryWheel();
    }
    #endregion

    #region Implementations
    public class Michelin : IWheel
    {
        public int GetTireWidth() { return 185; }
        public int GetAspectRatio() { return 55; }
    }

    public class GoodYear : IWheel
    {
        public int GetTireWidth() { return 185; }
        public int GetAspectRatio() { return 65; }
    }

    public class M16A : IEngine
    {
        public int GetHorsePower() { return 105; }
        public double GetVolume() { return 1.6; }
    }

    public class EW10J4S : IEngine
    {
        public int GetHorsePower() { return 175; }
        public double GetVolume() { return 2.0; }
    }

    public class Peugeot206CC : IAbstractCarsFactory
    {
        public IEngine FactoryEngine() { return new EW10J4S(); }
        public IWheel FactoryWheel() { return new Michelin(); }
    }

    public class SuzukiLiana : IAbstractCarsFactory
    {
        public IEngine FactoryEngine() { return new M16A(); }
        public IWheel FactoryWheel() { return new GoodYear(); }
    }

    #endregion
}

Using by client (as UnitTest):
IAbstractCarsFactory liana = new SuzukiLiana();
IAbstractCarsFactory peugeot = new Peugeot206CC();

IEngine lianaEngine = liana.FactoryEngine();
IEngine ccEngine = peugeot.FactoryEngine();

IWheel lianaWheel = liana.FactoryWheel();
IWheel ccWheel = peugeot.FactoryWheel();

Assert.AreEqual(lianaEngine.GetHorsePower(), 105, 0.01);
Assert.AreEqual(lianaEngine.GetVolume(), 1.6, 0.01);
Assert.AreEqual(ccEngine.GetHorsePower(), 175, 0.01);
Assert.AreEqual(ccEngine.GetVolume(), 2.0, 0.01);

Assert.AreEqual(lianaWheel.GetAspectRatio(), 65, 0.01);
Assert.AreEqual(lianaWheel.GetTireWidth(), 185, 0.01);
Assert.AreEqual(ccWheel.GetAspectRatio(), 55, 0.01);
Assert.AreEqual(ccWheel.GetTireWidth(), 185, 0.01);

Class Diagrams
Fig 1:class diagram without associations

Fig 2: class diagram with client associations

Fig 3: class diagram with associations inside of Abstract Factory

So, Abstract Factory, as other factories is creational pattern.
Main difference from Factory Method - is ability to create factory which can create many objects. In Factory Method there is single creator which can create object, but in Abstract Family can be a lot of creators, each can create specific object.
If we will redesign Abstract Factory abstract class to have only one creator, it will be looks, like a Factory Method. I just removed Engines from design. Described in Fig 4:

Fig 4:redesign to Factory Method

That's all
en → ru
объект
имя существительное: объект, предмет, цель, вещь, дополнение, несуразный человек, нелепая вещь
глагол: возражать, возразить, протестовать, не одобрять, не любить, не переносить
имя прилагательное: объектный, целевой, выходной

Monday, November 11, 2013

Factory Method Design pattern

Hello

First, i wish publish code and class diagram, and use it as a reference after.

Code:
namespace FactoryMethodDP
{
    public interface ICreatedClass
    {
        string GetName();
    }

    public class CreatedClassA : ICreatedClass
    {
        public string GetName() { return "A"; }
    }

    public class CreatedClassB : ICreatedClass
    {
        public string GetName() { return "B"; }
    }


    public interface ICreator
    {
        ICreatedClass FactoryMethod();
    }

    public class ConcreteCreatorA : ICreator
    {
        public ICreatedClass FactoryMethod() { return new CreatedClassA(); }
    }

    public class ConcreteCreatorB : ICreator
    {
        public ICreatedClass FactoryMethod() { return new CreatedClassB(); }
    }
}

Class Diagram:
Fig 1:class diagram without associations

Fig 2: class diagram with client associations

Fig 3: class diagram with associations inside of Factory Method

About class diagrams: while first is more simple, clear and understandable, the second closer to real life - there can be seen who should know about who.

Factory Method, like Simple Factory, served the client for creating objects without knowledge about objects, only about its interface. So, instantiation of objects is encapsulated

But, there is some differences between Factory Method and Simple Factory
There some minor differences, like static method in Simple Factory etc. The really goal, IMHO, Factory Method do not violates Open-Closed Principle. As a developer, you can add pairs (pair, because if add Created class need add Creator class too. In current design) of classes without need to change other classes. 
For example, let's think about CPU Factory Method.  Approach of adding new type of CPU (for example ARM) is different in Simple Factory and Factory Method. 
In Simple Factory i need add enum and change factory class (in switch statement i should add new case, so it Open-Closed Principle violation). 
In Factory Method i only add pairs of classes (one implements ICreator and other implements ICreatedClass), without change other classes (Fig 1).

Client, in both Design Patterns, should knows 3 things (Fig 2): 
  • interface of created object
  • interface of creator 
  • concrete creators in Factory Method and enum in Simple Factory
 So, here both patterns are same +-.

That's all

Simple Factory Design Pattern

Hello

It is very reasonable and simple code structure: create different objects in run-time

But, it violate Open-Closed Principle. Why? If we add new constructed type we need change enum and change SimpleFactory.
But, do not worry, maybe it will feet Your needs. Maybe Types will never be added. For example, there 12 types of months and in future no month will be added, becouse there is no 13 months in year :-)

Class Diagram:





Client should know:
1. Which object to create. It can be enum (like in example, "ObjectType") or string or something else.
2. SimpleFactory and its static method Create
3. Created object interface (like in example, "IFactoryInterface")

My example - is factory of processors: Intel, AMD and VIA

Code example:

Code:
namespace SimpleFactoryDP
{
    public enum CPUType { Intel, AMD, VIA, }

    public interface ICPU
    {
        string GetName();
        double GetSpeed();
        int GetPinsAmount();
    }

    public static class CPUFactory
    {
        public static ICPU Create(CPUType type)
        {
            ICPU cpu = null;

            switch (type)
            {
                case CPUType.AMD:
                    cpu = new AMD();
                    break;
                case CPUType.Intel:
                    cpu = new Intel();
                    break;
                case CPUType.VIA:
                    cpu = new VIA();
                    break;
            }

            return cpu;
        }
    }

    public class Intel : ICPU
    {
        public string GetName() { return "Intel CPU. Very Good CPU"; }
        public double GetSpeed() { return 6.78; }
        public int GetPinsAmount() { return 400; }
    }

    public class AMD : ICPU
    {
        public string GetName() { return "AMD CPU. Very Well and cheap CPU"; }
        public double GetSpeed() { return 5.99; }
        public int GetPinsAmount() { return 420; }
    }

    public class VIA : ICPU
    {
        public string GetName() { return "VIA CPU. Very Cheap"; }
        public double GetSpeed() { return 4.11; }
        public int GetPinsAmount() { return 100; }
    }
}

Using:
ICPU cpuIntel = CPUFactory.Create(CPUType.Intel);
Assert.AreEqual(cpuIntel.GetName(), "Intel CPU. Very Good CPU");
Assert.AreEqual(cpuIntel.GetSpeed(), 6.78);
Assert.AreEqual(cpuIntel.GetPinsAmount(), 400);

That's all

Factory family

Hello

There is 3 factory related design patterns:

1. Simple Factory
2. Abstract Factory
3. Factory Method

Every one from this Design Patterns served for creation of objects. Instantiation of objects to created is incapsulated.

I will give examples for each one

Sunday, November 10, 2013

Decorator design pattern

Hello

There is code example of Decorator design pattern. Decorator design pattern allows to add functionality or change behaviour  in run time, not like a static add functionality AKA inheritance.
My examples is pretty simple:
1. There is simple calculator, which knows how to perform 2 basic operations - adding and substrate numbers. Now I wish dynamically add functionality at run time. Here comes Decorator design pattern, which allows it.
2. Example from "Head First" book: there 2 basic coffee types: Brazilian and Arabica. But sometime i wish drink Arabica with double milk and sugar. Again, here comes Decorator design pattern, which allows it.
IMHO, there is no additional responsibilities, but it very close to Decorator.

Calculator 

Code:
namespace DecoratorDP
{
    public interface ISimpleCalculator
    {
        double Add(double a, double b);
        double Subs(double a, double b);
    }

    public class SimpleCalculator : ISimpleCalculator
    {
        public double Add(double a, double b)
        {
            return a + b;
        }

        public double Subs(double a, double b)
        {
            return a - b;
        }
    }

    public interface IAdvancedCalculator : ISimpleCalculator
    {
        double Mul(double a, double b);
        double Div(double a, double b);
    }

    public class AdvancedCalculator : IAdvancedCalculator
    {
        private ISimpleCalculator _simpleCalculator;

        public AdvancedCalculator(ISimpleCalculator simpleCalculator)
        {
            _simpleCalculator = simpleCalculator;
        }

        public double Mul(double a, double b)
        {
            return a * b;
        }

        public double Div(double a, double b)
        {
            return a / b;
        }

        public double Add(double a, double b)
        {
            return _simpleCalculator.Add(a, b);
        }

        public double Subs(double a, double b)
        {
            return _simpleCalculator.Subs(a, b);
        }
    }
}

Using:
ISimpleCalculator sc1 = new SimpleCalculator();
Assert.AreEqual(sc1.Add(5, 6), 11);
Assert.AreEqual(sc1.Subs(5, 6), -1);

IAdvancedCalculator ac = new AdvancedCalculator(sc1);
Assert.AreEqual(ac.Add(5, 6), 11);
Assert.AreEqual(ac.Subs(5, 6), -1);
Assert.AreEqual(ac.Mul(5, 6), 30);
Assert.AreEqual(ac.Div(66, 6), 11);

Class Diagram:

Coffee

Code:
using System;

namespace DecoratorDP
{
    public interface IBaseCofee
    {
        String GetName();
        double GetPrice();
    }

    public class ArabicaCofee : IBaseCofee
    {
        public string GetName() { return "Arabica coffee"; }
        public double GetPrice() { return 6.7; }
    }

    public class BrazilianCofee : IBaseCofee
    {
        public string GetName() { return "Brazilian coffee"; }
        public double GetPrice() { return 4.6; }
    }

    public interface IAdvancedCofee : IBaseCofee { }

    public class CofeeWithMilk : IAdvancedCofee
    {
        private IBaseCofee _coffee;

        public CofeeWithMilk(IBaseCofee coffee)
        {
            _coffee = coffee;
        }

        public string GetName()
        {
            return "Milk + " + _coffee.GetName();
        }

        public double GetPrice()
        {
            return 1.2 + _coffee.GetPrice();
        }
    }

    public class CofeeWithSugar : IAdvancedCofee
    {
        private IBaseCofee _coffee;

        public CofeeWithSugar(IBaseCofee coffee)
        {
            _coffee = coffee;
        }

        public string GetName()
        {
            return "Sugar + " + _coffee.GetName();
        }

        public double GetPrice()
        {
            return 0.3 + _coffee.GetPrice();
        }
    }
}

Using:
IBaseCofee baseArabica = new ArabicaCofee();
Assert.AreEqual(baseArabica.GetPrice(), 6.7);
Assert.AreEqual(baseArabica.GetName(), "Arabica coffee");

IBaseCofee baseBrazilian = new BrazilianCofee();
Assert.AreEqual(baseBrazilian.GetPrice(), 4.6);
Assert.AreEqual(baseBrazilian.GetName(), "Brazilian coffee");

IBaseCofee coffeeWithMilk = new CofeeWithMilk(baseArabica);
Assert.AreEqual(coffeeWithMilk.GetPrice(), 7.9);
Assert.AreEqual(coffeeWithMilk.GetName(), "Milk + Arabica coffee");

IBaseCofee coffeeWithDoubleMilk = new CofeeWithMilk(new CofeeWithMilk(baseArabica));
Assert.AreEqual(coffeeWithDoubleMilk.GetPrice(), 9.1);
Assert.AreEqual(coffeeWithDoubleMilk.GetName(), "Milk + Milk + Arabica coffee");

IBaseCofee coffeeWithDoubleMilkDoubleSugar = new CofeeWithSugar(new CofeeWithSugar(new CofeeWithMilk(new CofeeWithMilk(baseArabica))));
Assert.AreEqual(coffeeWithDoubleMilkDoubleSugar.GetPrice(), 9.7, 0.01);
Assert.AreEqual(coffeeWithDoubleMilkDoubleSugar.GetName(), "Sugar + Sugar + Milk + Milk + Arabica coffee");

Class Diagram:


that's it

Observer design pattern from Real World

Hello
Observer design pattern well described here: WIKI: Observer pattern

I wish give some real example.

So, example...
My example is: GUI for creating controls + share information between:

My UI is very simple: 2 buttons + text box:

Add listener button, which create UserControl and subscribe it
Remove listener: remove UserControl and detach it
Text box: when it updates, each UserControl get informed about new text

UserControl:
Lable: show Subject status
TextBox: can be updated, so updated text goes to Subject and from Subject to each Observer:

And, if i wish talk with pictures:

Start app:

Add listener:


Add 1 more listener:

Now, main UI set text ("hello") in its textbox, so each listener get it ("hello") and show in own lable:

And, 1-st listener can set its text ("mama") in its textbox:
and we see, "mama" is updated for each listener


Now, main UI set new text ("papa") in its textbox, so each listener get it ("papa") and show in own lable:

Code

Solution:

IObserver.cs:
namespace ObserverFormDP
{
    public interface IObserver
    {
        void StateUpdate();
    }
}

ISubject.cs:
using System;

namespace ObserverFormDP
{
    public interface ISubject
    {
        String State { get; set; }
        void Attach(IObserver obsever);
        void Detach(IObserver obsever);
        void Notify();
    }
}

Subject.cs:
using System.Collections.Generic;

namespace ObserverFormDP
{
    public class Subject : ISubject
    {
        private string _state;
        private List<IObserver> _attachedObservers;

        public Subject()
        {
            _attachedObservers = new List<IObserver>();
        }

        public void Attach(IObserver obsever)
        {
            _attachedObservers.Add(obsever);
        }

        public void Detach(IObserver obsever)
        {
            _attachedObservers.Remove(obsever);
        }

        public void Notify()
        {
            foreach (IObserver o in _attachedObservers)
            {
                o.StateUpdate();
            }
        }

        public string State
        {
            get
            {
                return _state;
            }
            set
            {
                _state = value;
                Notify();
            }
        }
    }
}

UserControl1:
using System.Windows.Forms;

namespace ObserverFormDP
{
    public partial class UserControl1 : UserControl, IObserver
    {
        private ISubject _subject;

        public UserControl1(ISubject subject)
        {
            InitializeComponent();

            _subject = subject;
        }

        public void StateUpdate()
        {
            label1.Text = _subject.State;
        }

        private void textBox1_TextChanged(object sender, System.EventArgs e)
        {
            _subject.State = textBox1.Text;
        }
    }
}

Form1:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace ObserverFormDP
{
    public partial class Form1 : Form
    {
        List<IObserver> _observers;
        ISubject _subject;

        public Form1()
        {
            InitializeComponent();
            _observers = new List<IObserver>();
            _subject = new Subject();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            UserControl1 uc1 = new UserControl1(_subject);
            _observers.Add(uc1);
            _subject.Attach(uc1);
            uc1.Location = new Point(_observers.Count * 110, 20);
            Controls.Add(uc1);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (_observers.Count == 0) return;
            IObserver o = _observers[_observers.Count - 1];
            Controls.Remove(o as UserControl);
            _observers.Remove(o);
            _subject.Attach(o);
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            _subject.State = textBox1.Text;
        }
    }
}

Thats all

Thanks,
Efim

Thursday, November 7, 2013

Refactoring classes to Strategy and State design patterns

Hi,
Today i try use 2 behavioral design pattern: Strategy and State design patterns. About this patterns there a lot of stuff in net. I wish try use some refactoring, for moving poor designed class to better designed, by using Strategy and State design patterns.

In my example i do calculations of taxes for products depend on season. For example, in Summer, tax for product, which costs 100 units not same, as a tax in Winter for product, which costs 150 units. So, there is system of tax calculation, depends on season and product price.

Lets design!

Bang!

namespace SeasonTaxesNoDP

{
    public class SeasonTaxes
    {
        public enum Season { Spring, Summer, Autumn, Winter, }

        Season _season;

        public SeasonTaxes()
        {
            _season = Season.Spring;
        }

        public void NextSeason()
        {
            switch (_season)
            {
                case Season.Autumn:
                    _season = Season.Winter;
                    break;
                case Season.Spring:
                    _season = Season.Summer;
                    break;
                case Season.Summer:
                    _season = Season.Autumn;
                    break;
                case Season.Winter:
                    _season = Season.Spring;
                    break;
            }
        }

        public void PreviousSeason()
        {
            switch (_season)
            {
                case Season.Autumn:
                    _season = Season.Summer;
                    break;
                case Season.Spring:
                    _season = Season.Winter;
                    break;
                case Season.Summer:
                    _season = Season.Spring;
                    break;
                case Season.Winter:
                    _season = Season.Autumn;
                    break;
            }
        }

        public double CalculateTax(double productPrice)
        {
            switch (_season)
            {
                case Season.Autumn:
                    if (productPrice > 180)
                    {
                        return productPrice * 0.32 + 11.2;
                    }
                    else
                    {
                        return productPrice * 0.32 + 13.2;
                    }
                case Season.Spring:
                    if (productPrice > 170)
                    {
                        return productPrice * 0.52 + 15.2;
                    }
                    else
                    {
                        return productPrice * 0.42 + 17.2;
                    }
                case Season.Summer:
                    if (productPrice > 300)
                    {
                        return productPrice * 0.72 + 21.2;
                    }
                    else
                    {
                        return productPrice * 0.42 + 23.2;
                    }
                case Season.Winter:
                    if (productPrice > 220)
                    {
                        return productPrice * 0.342 + 11.2;
                    }
                    else
                    {
                        return productPrice * 0.562 + 16.2;
                    }
            }
            return 0.0;
        }
    }
}

Using:
        private static void f4()
        {
            SeasonTaxesNoDP.SeasonTaxes season = new SeasonTaxesNoDP.SeasonTaxes();
            season.CalculateTax(345);

            season.NextSeason();
            season.CalculateTax(567);
        }

SeasonTaxes is an Finite-state machine (FSM) of seasons + system of calculations, so it do 2 things. So it have 2 axis of changes: if there change system of calculations it will change or if there change in FSM it will change too. So, it violates The Single Responsibility Principle (SRP).

This code is hard to understand and hard to maintenance.

If i will add new season, it will violate Open - Close principle (OCP)
If i will remove season, same.
Same about system of calculations.

Lets do refactoring.
I will move to State design pattern, so i wish move the FSM out from the class. It will remove one axis of potential changes: changes in Seasons switch machine


Code:
namespace SeasonTaxesStateDP
{
    public abstract class SeasonState
    {
        public abstract void NextSeason(SeasonTaxes seasonTaxes);
        public abstract void PreviousSeason(SeasonTaxes seasonTaxes);
        public abstract double CalculateTax(double productPrice);
    }

    public class SpringSeasonState : SeasonState
    {
        public override void NextSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new SummerSeasonState(); }
        public override void PreviousSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new WinterSeasonState(); }

        public override double CalculateTax(double productPrice)
        {
            if (productPrice > 170)
            {
                return productPrice * 0.52 + 15.2;
            }
            else
            {
                return productPrice * 0.42 + 17.2;
            }
        }
    }

    public class AutumnSeasonState : SeasonState
    {
        public override void NextSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new WinterSeasonState(); }
        public override void PreviousSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new SummerSeasonState(); }

        public override double CalculateTax(double productPrice)
        {
            if (productPrice > 180)
            {
                return productPrice * 0.32 + 11.2;
            }
            else
            {
                return productPrice * 0.32 + 13.2;
            }
        }
    }

    public class SummerSeasonState : SeasonState
    {
        public override void NextSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new AutumnSeasonState(); }
        public override void PreviousSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new SpringSeasonState(); }

        public override double CalculateTax(double productPrice)
        {
            if (productPrice > 300)
            {
                return productPrice * 0.72 + 21.2;
            }
            else
            {
                return productPrice * 0.42 + 23.2;
            }
        }
    }

    public class WinterSeasonState : SeasonState
    {
        public override void NextSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new SpringSeasonState(); }
        public override void PreviousSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new AutumnSeasonState(); }

        public override double CalculateTax(double productPrice)
        {
            if (productPrice > 220)
            {
                return productPrice * 0.342 + 11.2;
            }
            else
            {
                return productPrice * 0.562 + 16.2;
            }
        }
    }

    public class SeasonTaxes
    {
        public SeasonState State { get; set; }

        public SeasonTaxes()
        {
            State = new SpringSeasonState();
        }

        public void NextSeason()
        {
            State.NextSeason(this);
        }

        public void PreviousSeason()
        {
            State.PreviousSeason(this);
        }

        public double CalculateTax(double productPrice)
        {
            return State.CalculateTax(productPrice);
        }
    }
}


Class SeasonTaxes get smaller and simpler. It is delegates responsibilities to SeasonState implementations. 
But, each implementation of SeasonState  violates OCP and SRP. 

So, i did not like calculations in State classes. 
It is looks, like a mess.
I wish move tax calculations out from FSM.
Lets do refactoring to Strategy design pattern:


Code:
namespace SeasonTaxesStateStrategyDP
{
    public interface IStrategyTax
    {
        double CalculateTax(double productPrice);
    }

    public class SpringStrategyTax : IStrategyTax
    {
        public double CalculateTax(double productPrice)
        {
            if (productPrice > 170)
            {
                return productPrice * 0.52 + 15.2;
            }
            else
            {
                return productPrice * 0.42 + 17.2;
            }
        }
    }

    public class AutumnStrategyTax : IStrategyTax
    {
        public double CalculateTax(double productPrice)
        {
            if (productPrice > 180)
            {
                return productPrice * 0.32 + 11.2;
            }
            else
            {
                return productPrice * 0.32 + 13.2;
            }
        }
    }

    public class SummerStrategyTax : IStrategyTax
    {
        public double CalculateTax(double productPrice)
        {
            if (productPrice > 300)
            {
                return productPrice * 0.72 + 21.2;
            }
            else
            {
                return productPrice * 0.42 + 23.2;
            }
        }
    }

    public class WinterStrategyTax : IStrategyTax
    {
        public double CalculateTax(double productPrice)
        {
            if (productPrice > 220)
            {
                return productPrice * 0.342 + 11.2;
            }
            else
            {
                return productPrice * 0.562 + 16.2;
            }
        }
    }

    public abstract class SeasonState
    {
        public abstract void NextSeason(SeasonTaxes seasonTaxes);
        public abstract void PreviousSeason(SeasonTaxes seasonTaxes);

        protected IStrategyTax _strategyTax;

        public double CalculateTax(double productPrice)
        {
            return _strategyTax.CalculateTax(productPrice);
        }
    }

    public class SpringSeasonState : SeasonState
    {
        public override void NextSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new SummerSeasonState(); }
        public override void PreviousSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new WinterSeasonState(); }
    }

    public class AutumnSeasonState : SeasonState
    {
        public override void NextSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new WinterSeasonState(); }
        public override void PreviousSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new SummerSeasonState(); }
    }

    public class SummerSeasonState : SeasonState
    {
        public override void NextSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new AutumnSeasonState(); }
        public override void PreviousSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new SpringSeasonState(); }
    }

    public class WinterSeasonState : SeasonState
    {
        public override void NextSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new SpringSeasonState(); }
        public override void PreviousSeason(SeasonTaxes seasonTaxes) { seasonTaxes.State = new AutumnSeasonState(); }
    }

    public class SeasonTaxes
    {
        public SeasonState State { get; set; }

        public SeasonTaxes()
        {
            State = new SpringSeasonState();
        }

        public void NextSeason()
        {
            State.NextSeason(this);
        }

        public void PreviousSeason()
        {
            State.PreviousSeason(this);
        }

        public double CalculateTax(double productPrice)
        {
            return State.CalculateTax(productPrice);
        }
    }
}

that's it