Monday, October 8, 2012

Strategy Pattern

*Disclaimer these writings are for my own learning purposes not as advice to others. If any part is incorrect please feel free to politely discuss. 

The Strategy Pattern is known as a behavioral pattern.
The keys to achieving the pattern are to encapsulate a family of algorithms, let those algorithms be interchangeable.

Here is my example: (C#)

In this example (Expansion of example used in wikipedia) we will take a car class and implement a family of brake behaviors. Notice the braking functionality is swappable at runtime.
Here's a link to a solution complete with a little console app to see it run.
Strategy Pattern Car example


*Note the dependency injection in this example. Its being achieved through a technique called "Constructor injection". If you have read Martin Fowler's inversion of control writings you have probably seen him talk about how an assembler piece can be responcible for injecting the implementation.
I'm my example my client is my assembler, and it is injecting the brake behavior implementation through constructor injection.


//Interface
  public interface IBrakeBehavior
  {
        bool Brake(int speed, Condition condition, int distance);
  }

//Base class car
   public class Car
    {
        private IBrakeBehavior brakeStrat;
        public Car(IBrakeBehavior brakeStrategy)
        {
            brakeStrat = brakeStrategy;
        }

        public bool ApplyBrakes(int speed, Condition cond, int distance)
        {
            return brakeStrat.Brake(speed, cond, distance);
        }
    }

//Various BrakeTypes that implement brakebehavior in their own way.
//DiskBrake Algorithm example 1
class DiskBrake : IBrakeBehavior
    {
        private static readonly int BrakeEfficiency = 2;

        public bool Brake(int speed, Condition condition, int distance)
        {
            switch (condition)
            {
                case Condition.dry:
                    return (speed * BrakeEfficiency) * 1 > distance ? false : true;
                case Condition.ice:
                    return (speed * BrakeEfficiency) * 1.7 > distance ? false : true;
                case Condition.snow:
                    return (speed * BrakeEfficiency) * 1.5 > distance ? false : true;
                case Condition.wet:
                    return (speed * BrakeEfficiency) * 1.2 > distance ? false : true;
                default:
                    return false;
            }
        }
    }

//DrumBrake Algorithm example 2
class DrumBrake : IBrakeBehavior
    {
        private static readonly int BrakeEfficiency = 3;

        public bool Brake(int speed, Condition condition, int distance)
        {
            switch (condition)
            {
                case Condition.dry:
                    return (speed * BrakeEfficiency) * 1 > distance ? false : true;
                case Condition.ice:
                    return (speed * BrakeEfficiency) * 1.7 > distance ? false : true;
                case Condition.snow:
                    return (speed * BrakeEfficiency) * 1.5 > distance ? false : true;
                case Condition.wet:
                    return (speed * BrakeEfficiency) * 1.2 > distance ? false : true;
                default:
                    return false;
            }
        }
    }

//ABSBrake Algorithm example 3
class ABSBrake : IBrakeBehavior
    {
        private static readonly int BrakeEfficiency = 1;

        public bool Brake(int speed, Condition condition, int distance)
        {
            switch (condition)
            {
                case Condition.dry:
                    return (speed * BrakeEfficiency) * 1 > distance ? false : true;
                case Condition.ice:
                    return (speed * BrakeEfficiency) * 1.7 > distance ? false : true;
                case Condition.snow:
                    return (speed * BrakeEfficiency) * 1.5 > distance ? false : true;
                case Condition.wet:
                    return (speed * BrakeEfficiency) * 1.2 > distance ? false : true;
                default:
                    return false;
            }
        }
    }

//Type of car using a certain braking algorithm
  public class ClassicCar : Car
    {
        public ClassicCar(IBrakeBehavior brakeBehave)
            : base(brakeBehave)
        { }
    }

//Another
 public class SportsCar : Car
    {
        public SportsCar(IBrakeBehavior brakeBehave)
            : base(brakeBehave)
        { }
    }

//Another
public class SUV : Car
    {
        public SUV(IBrakeBehavior brakeType)
            : base(brakeType)
        { }
    }

No comments:

Post a Comment