Showing posts with label Design Pattern. Show all posts
Showing posts with label Design Pattern. Show all posts

Wednesday, December 11, 2013

Refactoring to Decorator design pattern.

Hello

There was post about it (decorator-design-pattern), but lets do it better.

First of all i wish do it w/o using Design patterns, but using usual OOP principles.

So, i am a AM General company, witch making Hummer H1 army cars.

Lets do it!
I wish create car with two fields: weight and description

public interface IArmyCar
{
 int Weight { get; }
 string Description { get; }
}

public class Hummer : IArmyCar
{
 public Hummer() { }

 public int Weight
 {
  get { return 5000; }
 }

 public string Description
 {
  get { return "Hummer car"; }
 }
}

Great!
After some time, US army wish complete the car with some additions: Xenon lights. Lets do it:

public interface IArmyCar
{
 int Weight { get; }
 string Description { get; }
}

public class Hummer : IArmyCar
{
 public Hummer() { }

 public int Weight
 {
  get { return 5000; }
 }

 public string Description
 {
  get { return "Hummer car"; }
 }
}

public class CarExtraLights : IArmyCar
{
 public CarExtraLights() { }

 public int Weight
 {
  get { return 5020; }
 }

 public string Description
 {
  get { return "Hummer car + strong lights"; }
 }
}

Very simple. I just need remember how much kg in Hummer H1 when i do weight calculations and description of Hummer H1 when i return descriptions. But it does not gonna be changed FOR A NOW.

We sell very well cars to US army and do a lot of money.
After some time we get some new requirement. Texas state wish extra accumulator, because of Texas rangers like to play country music all the night in Hummer.
OK, no problem!

public interface IArmyCar
{
 int Weight { get; }
 string Description { get; }
}

public class Hummer : IArmyCar
{
 public Hummer() { }

 public int Weight
 {
  get { return 5000; }
 }

 public string Description
 {
  get { return "Hummer car"; }
 }
}

public class CarExtraLights : IArmyCar
{
 public CarExtraLights() { }

 public int Weight
 {
  get { return 5020; }
 }

 public string Description
 {
  get { return "Hummer car + strong lights"; }
 }
}

public class CarExtraAccumulator : IArmyCar
{
 public CarExtraAccumulator() { }

 public int Weight
 {
  get { return 5100; }
 }

 public string Description
 {
  get { return "Hummer car + big accumulator"; }
 }
}

Peace of cake!!! Just remember Hummer weight and description

Fine. US army, as all armies in the world wish equip cars with shield and gun! A lot of money for us! Lets do it:

public interface IArmyCar
{
 int Weight { get; }
 string Description { get; }
}

public class Hummer : IArmyCar
{
 public Hummer() { }

 public int Weight
 {
  get { return 5000; }
 }

 public string Description
 {
  get { return "Hummer car"; }
 }
}

public class CarShield : IArmyCar
{
 public CarShield() { }

 public int Weight
 {
  get { return 6000; }
 }

 public string Description
 {
  get { return "Hummer car + shield"; }
 }
}

public class CarArmor : IArmyCar
{
 public CarArmor() { }

 public int Weight
 {
  get { return 5200; }
 }

 public string Description
 {
  get { return "Hummer car + MAG"; }
 }
}

public class CarExtraLights : IArmyCar
{
 public CarExtraLights() { }

 public int Weight
 {
  get { return 5020; }
 }

 public string Description
 {
  get { return "Hummer car + strong lights"; }
 }
}

public class CarExtraAccumulator : IArmyCar
{
 public CarExtraAccumulator() { }

 public int Weight
 {
  get { return 5100; }
 }

 public string Description
 {
  get { return "Hummer car + big accumulator"; }
 }
}

Very good!

We are great company and we recruited new mechanical engineer, which make H1 stronger and lighter! Great success!!! But... now i need recalculate all Weight fields from all classes... OK, lets do it. Now H1 weight is 4500 kg:


public interface IArmyCar
{
 int Weight { get; }
 string Description { get; }
}

public class Hummer : IArmyCar
{
 public Hummer () { }

 public int Weight
 {
  get { return 4500; }
 }

 public string Description
 {
  get { return "Hummer car"; }
 }
}

public class CarShield : IArmyCar
{
 public CarShield() { }

 public int Weight
 {
  get { return 5500; }
 }

 public string Description
 {
  get { return "Hummer car + shield"; }
 }
}

public class CarArmor : IArmyCar
{
 public CarArmor() { }

 public int Weight
 {
  get { return 4700; }
 }

 public string Description
 {
  get { return "Hummer car + MAG"; }
 }
}

public class CarExtraLights : IArmyCar
{
 public CarExtraLights() { }

 public int Weight
 {
  get { return 4520; }
 }

 public string Description
 {
  get { return "Hummer car + strong lights"; }
 }
}

public class CarExtraAccumulator : IArmyCar
{
 public CarExtraAccumulator() { }

 public int Weight
 {
  get { return 4600; }
 }

 public string Description
 {
  get { return "Hummer car + big accumulator"; }
 }
}

Of course, we violate Open close principle, but for a now it is all changes.

After 3 month France army wish buy 10000 Hummers, equipped with extra accumulator and strong lights. OK... it is a lot of money!
Lets add CarExtraAccumulatorExtraLights class:

public interface IArmyCar
{
 int Weight { get; }
 string Description { get; }
}

public class Hummer : IArmyCar
{
 public Hummer () { }

 public int Weight
 {
  get { return 4500; }
 }

 public string Description
 {
  get { return "Hummer car"; }
 }
}

public class CarShield : IArmyCar
{
 public CarShield() { }

 public int Weight
 {
  get { return 5500; }
 }

 public string Description
 {
  get { return "Hummer car + shield"; }
 }
}

public class CarArmor : IArmyCar
{
 public CarArmor() { }

 public int Weight
 {
  get { return 4700; }
 }

 public string Description
 {
  get { return "Hummer car + MAG"; }
 }
}

public class CarExtraLights : IArmyCar
{
 public CarExtraLights() { }

 public int Weight
 {
  get { return 4520; }
 }

 public string Description
 {
  get { return "Hummer car + strong lights"; }
 }
}

public class CarExtraAccumulator : IArmyCar
{
 public CarExtraAccumulator() { }

 public int Weight
 {
  get { return 4600; }
 }

 public string Description
 {
  get { return "Hummer car + big accumulator"; }
 }
}

public class CarExtraAccumulatorExtraLights : IArmyCar
{
 public CarExtraAccumulator() { }

 public int Weight
 {
  get { return 4500 + 100 + 20; }
 }

 public string Description
 {
  get { return "Hummer car + big accumulator + strong lights"; }
 }
}

Looks no bad. But we need remember H1 weight, accumulator weight, lights weight.

After 2 weeks H1 weight changed, accumulator weight changed but lights weight do not. After month some country wish buy H1 + armor. After 2 months other country wish H1 + Lights+ armor.
After 1 year we have 1000 classes, because some countries wish 3 guns and 6 accumulators on H1!!!! Oh my god! And after 2 years we have 20000 classes...


And after all H1 weight changed again... 
I quit! No more! I started take anti-anxiety medication and it helps me.

But, fortunately i find time-machine !!!!

And i go back in the time to learn patterns and change H1 project!

From http://www.dofactory.com i read: "Decorators provide a flexible alternative to subclassing for extending functionality".

It is exactly what i need! Change behaviour of object on the fly!

After 2 hours of programming i got it!

public interface IArmyCar
{
 int Weight { get; }
 string Description { get; }
}

public class Hummer : IArmyCar
{
 public Hummer () { }

 public int Weight
 {
  get { return 5000; }
 }

 public string Description
 {
  get { return "Hummer car"; }
 }
}

public abstract class CarDecorator : IArmyCar
{
 protected int _weight;
 protected string _description;

 public int Weight
 {
  get { return _weight; }
 }

 public string Description
 {
  get { return _description; }
 }
}

public class CarShield : CarDecorator
{
 public CarShield(IArmyCar ac)
 {
  _weight = 1000 + ac.Weight;
  _description = ac.Description + " + shield";
 }
}

public class CarArmor : CarDecorator
{
 public CarArmor(IArmyCar ac)
 {
  _weight = 200 + ac.Weight;
  _description = ac.Description + " + MAG";
 }
}

public class CarExtraLights : CarDecorator
{
 public CarExtraLights(IArmyCar ac)
 {
  _weight = 20 + ac.Weight;
  _description = ac.Description + " + strong lights";
 }
}

public class CarExtraAccumulator : CarDecorator
{
 public CarExtraAccumulator(IArmyCar ac)
 {
  _weight = 100 + ac.Weight;
  _description = ac.Description + " + big accumulator";
 }
}

And using... We use it like build cabbage in our self: adding layer by layer, layer by layer.
Lets create H1with 3 accumulators and 3 guns:

IArmyCar ac = new Hummer();
Console.WriteLine("Weight: {0}, description: {1}", ac.Weight, ac.Description);

ac = new CarArmor(new CarArmor(new CarArmor(
 new CarExtraAccumulator(new CarExtraAccumulator(new CarExtraAccumulator(new Hummer()))))));
Console.WriteLine("Weight: {0}, description: {1}", ac.Weight, ac.Description);

Output:
Weight: 5000, description: Hummer car
Weight: 5900, description: Hummer car + big accumulator + big accumulator + big accumulator + MAG + MAG + MAG

Press any key to continue . . .

Moreover, i do not need care about changes in weight of other parts! If, for example, weight of accumulator changed, it not influence on other classes!!! All decorators are phlegmatic to each other!!!
That's all.


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

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