Wednesday, December 31, 2014

Command design pattern. Simple version.

Hello
We have Light devices, which can beam or not.
We do not want control directly Light source, because we want learn Command Design Pattern :-)
Of course, the reasons is others. For example, we want to be less sensitive to changes.

In implementation of Command Design Patter in our example we have 3 players:

  • Device: is a Light which can be "ON" or "OFF" state.
  • Command turn "ON" the lights: is Light "ON" command. Is a class, which wraps above Light. Heart of this class - turn "ON" the Light, which encapsulated in single function "Execute". 
  • Remote: some class which got command and call it "Execute". When user call "Click Remote" of this class, its method call "Execute" of command
Illustration:




Code behind it:
public interface ICommand
{
    void Execute();
}

public class Light
{
    public void On()
    {
        Console.WriteLine("Light is ON");
    }

    public void Off()
    {
        Console.WriteLine("Light is OFF");
    }
}

public class LightOnCommand : ICommand
{
    private Light _light;

    public LightOnCommand(Light light)
    {
        _light = light;
    }

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

public class SimpleRemoteControl
{
    ICommand _command;

    public void SetCommand(ICommand command)
    {
        _command = command;
    }

    public void ClickButton()
    {
        _command.Execute();
    }
}

Tester:
Light light = new Light();
ICommand lightOnCmd = new LightOnCommand(light);

SimpleRemoteControl remote = new SimpleRemoteControl();
remote.SetCommand(lightOnCmd);
remote.ClickButton();

Result:

Wednesday, December 17, 2014

Decorator Design Pattern - another example

Hi all

Another example of Decorator Design pattern implementation - create text decorator. For example, i create string. My goal - create architecture, which makes possible to change string on the fly - change register, remove spaces etc

My Unit Test shall looks like:

Component component = new LowerRegisterDecorator(new RemoveSpacesDecorator(new BaseString("MaMa PaPa")));
string text = component.Text();

Expected result: mamapapa

Lets coding
First of all, UML:

Code:

class BaseComponent.cs:

namespace TextDecorator
{
    public class BaseString : Component
    {
        private string _text;

        public BaseString(string text)
        {
            _text = text;
        }

        public override string Text()
        {
            return _text;
        }
    }
}

Class Component.cs:

using System;

namespace TextDecorator
{
    public abstract class Component
    {
        public abstract String Text();
    }
}

Class ComponentDecorator.cs:

namespace TextDecorator
{
    public abstract class ComponentDecorator : Component
    {
        protected Component _component;
        public ComponentDecorator(Component component)
        {
            _component = component;
        }
    }

    public class UpperRegisterDecorator : ComponentDecorator
    {
        public UpperRegisterDecorator(Component component) : base(component) { }

        public override string Text()
        {
            return _component.Text().ToUpper();
        }
    }

    public class LowerRegisterDecorator : ComponentDecorator
    {
        public LowerRegisterDecorator(Component component) : base(component) { }

        public override string Text()
        {
            return _component.Text().ToLower();
        }
    }
    
    public class RemoveSpacesDecorator : ComponentDecorator
    {
        public RemoveSpacesDecorator(Component component) : base(component) { }

        public override string Text()
        {
            return _component.Text().Replace(" ","");
        }
    }
}

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

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
объект
имя существительное: объект, предмет, цель, вещь, дополнение, несуразный человек, нелепая вещь
глагол: возражать, возразить, протестовать, не одобрять, не любить, не переносить
имя прилагательное: объектный, целевой, выходной