Strategy pattern

A strategy pattern is a behavior pattern and allow selecting or change an algorithm at run time.

Generic strategy pattern example

First of all, let’s view on a generic example.

You need an interface and at least two classes, which are inherited from the interface with different implementations.

Furthermore, you need a context, where you can put the different strategies.

interface IStrategy
{
    void Algorithm();
}
class Strategy1 : IStrategy
{
    public void Algorithm() => Console.WriteLine("first strategy");
}
class Strategy2 : IStrategy
{
    public void Algorithm() => Console.WriteLine("second strategy");
}
class Context
{
    public IStrategy Strategy { get; set; }
    public Context(IStrategy strategy)
    {
        Strategy = strategy;
    }
    public void Operation()
    {
        Strategy.Algorithm();
    }
}

public class Client
{
    public void Main()
    {
        var context = new Context(new Strategy1());

        context.Operation(); // output: first strategy
        context.Strategy = new Strategy2();
        context.Operation(); // output: second strategy
    }
}

Create a real world strategy pattern example

I’ve prepared a little RPG game for you. It should symbolize a pvp fight between two warriors, which can switch the stance to make more damage or to have more defense against the attacker.

 

interface IStance
{
    double Attack { get; }
    double Defence { get; }
    string Name { get; }
}
class BalancedStance : IStance
{
    public double Attack { get; } = 1;
    public double Defence { get; } = 1;
    public string Name { get; } = "b";
}
class AgressiveStance : IStance
{
    public double Attack { get; } = 1.5;
    public double Defence { get; } = 0.7;
    public string Name { get; } = "a";
}
class DefensiveStance : IStance
{
    public double Attack { get; } = 0.7;
    public double Defence { get; } = 1.5;
    public string Name { get; } = "d";
}

 

class Warrior
{
    private Random _random = new Random();

    public int Life { get; set; } = 100;
    public string Name { get; set; }
    public IStance Stance { get; set; } = new BalancedStance();

    public Warrior(string name) => Name = name;

    public void Attack(Warrior other)
    {
        double damage = GetBaseDamage(9, 11);
        damage *= Stance.Attack;
        damage /= other.Stance.Defence;

        other.Life -= (int)damage;

        Console.WriteLine(
            $"{Name}({Stance.Name}) hit {other.Name}({other.Stance.Name})." +
            $" Life left: {other.Life}/100 (-{(int)damage})");
    }

    private double GetBaseDamage(int min, int max) =>
        _random.Next(max - min) + min;
}

 

public class Client
{
    public void Main()
    {
        var w1 = new Warrior("Bruce");
        var w2 = new Warrior("Chuck");

        w1.Attack(w2);

        w2.Stance = new AgressiveStance();
        w2.Attack(w1);

        w1.Stance = new DefensiveStance();
        w1.Attack(w2);

        w2.Attack(w1);

        w1.Stance = new AgressiveStance();
        w1.Attack(w2);

        w2.Stance = new DefensiveStance();
        w2.Attack(w1);

        w1.Attack(w2);

        w2.Attack(w1);

        w1.Stance = new BalancedStance();
        w1.Attack(w2);

        w2.Stance = new BalancedStance();
        w2.Attack(w1);
    }
}

Leave a Reply

Your email address will not be published.