Strategy pattern with dictionary

Strategy pattern with dictionary

Strategy Pattern with Dictionary

What is a good way to avoid if else statements ?

The answer is simple, use switch case statements :). But the question is what's even better ?

For this the answer that comes to my mind is Strategy pattern using dictionary. In this blog we will have a sneak into this pattern.

I would go for strategies if I have different entities who would perform the same operation in different styles. For example : If I am playing a game like football, each player in my team would have a different role (like goalkeeper, defender, striker). So to put this into OOPS, this is how we can design our application :

Strategy :

An abstract/interface which defines the strategy


Context : 

The context contains the strategies defined for different players. This is the place where the strategies are registered


Concrete classes implementing strategy : 

The actual strategies defined for different players are defined here.

Let's defined the strategy first :

I want to be able to define what a player is supposed to do with the football. So I create an interface as follows :

  /// <summary>
    /// a strategy defined for all the players in the team
    /// </summary>
    public interface IStrategy
    {
        void PlayingStrategyWith(Football ball);
    }

Then I create different strategies for the different kind of players as follows :

/// <summary>
    /// the job of the defender is to defend its field
    /// </summary>
    public class DefenderStrategy : IStrategy
    {
        public void PlayingStrategyWith(Football ball)
        {
            Console.WriteLine("defend the ball");
        }
    }
    
    /// <summary>
    /// the job of a forward is to striker a goal
    /// </summary>
    public class ForwardStrategy : IStrategy
    {
        public void PlayingStrategyWith(Football ball)
        {
            Console.WriteLine("strike the ball");
        }
    }
    
    /// <summary>
    /// the job of the goal keeper is to prevent goals
    /// </summary>
    public class GoalkeeperStrategy : IStrategy
    {
        public void PlayingStrategyWith(Football ball)
        {
            Console.WriteLine("defend goals");
        }
    }

Finally I create a context and register the strategies I have just defined as follows :

/// <summary>
    /// context in which strategies are well defined
    /// </summary>
    public class FiFaContext
    {
        public Dictionary<PlayerType, IStrategy> Strategies = new Dictionary<PlayerType, IStrategy>();
        public FiFaContext(Football ball)
        {
            Strategies.Add(PlayerType.Defender, new DefenderStrategy());
            Strategies.Add(PlayerType.Forward, new ForwardStrategy());
            Strategies.Add(PlayerType.GoalKeeper, new GoalkeeperStrategy());
        }

    }

As you can see in the context above I have used Dictionary to initialize my strategies. So now to trigger my strategies I just need to initialize my context.

class Program
    {
        static void Main(string[] args)
        {
            Football ball = new Football();
            FiFaContext context = new FiFaContext(ball);
            context.Strategies[PlayerType.GoalKeeper].PlayingStrategyWith(ball);
            Console.ReadLine();
        }
    }

So a very simple method to write a maintainable code :). The entire source code is as follows :

using System;
using System.Collections.Generic;

namespace StrategyPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Football ball = new Football();
            FiFaContext context = new FiFaContext(ball);
            context.Strategies[PlayerType.GoalKeeper].PlayingStrategyWith(ball);
            Console.ReadLine();
        }
    }
    
    /// <summary>
    /// context in which strategies are well defined
    /// </summary>
    public class FiFaContext
    {
        public Dictionary<PlayerType, IStrategy> Strategies = new Dictionary<PlayerType, IStrategy>();
        public FiFaContext(Football ball)
        {
            Strategies.Add(PlayerType.Defender, new DefenderStrategy());
            Strategies.Add(PlayerType.Forward, new ForwardStrategy());
            Strategies.Add(PlayerType.GoalKeeper, new GoalkeeperStrategy());
        }

    }
    
    /// <summary>
    /// created enumerations to be used in dictionary instead of string
    /// </summary>
    public enum PlayerType
    {
        Defender,
        Forward,
        GoalKeeper
    }
    
    /// <summary>
    /// the job of the defender is to defend its field
    /// </summary>
    public class DefenderStrategy : IStrategy
    {
        public void PlayingStrategyWith(Football ball)
        {
            Console.WriteLine("defend the ball");
        }
    }
    
    /// <summary>
    /// the job of a forward is to striker a goal
    /// </summary>
    public class ForwardStrategy : IStrategy
    {
        public void PlayingStrategyWith(Football ball)
        {
            Console.WriteLine("strike the ball");
        }
    }
    
    /// <summary>
    /// the job of the goal keeper is to prevent goals
    /// </summary>
    public class GoalkeeperStrategy : IStrategy
    {
        public void PlayingStrategyWith(Football ball)
        {
            Console.WriteLine("defend goals");
        }
    }
    
    /// <summary>
    /// a strategy defined for all the players in the team
    /// </summary>
    public interface IStrategy
    {
        void PlayingStrategyWith(Football ball);
    }

    /// <summary>
    /// Just created a simple football class for the sake of example :)
    /// </summary>
    public class Football
    {
        public int Diameter { get; set; }
        public void Bounces()
        {

        }
    }
}
Rohan Kulkarni

Sr. Azure Architect at Ennead Architects

8 年

Non-static methods also helps when writing Unit test cases, you can mock them easily

Vaibhav Tambolkar

Senior Software Engineer at Wolters Kluwer Tax & Accounting

8 年

IMO the only downside with this approach is you have to change static methods to non-static(instance) in order to call them through the strategy interface.

回复
Shoeb Sayyed

PRINCE2 | Web | Mobile | Cloud | Automation

8 年

maybe because it's on mobile. thanks for pointing it out man

回复
Vaibhav Tambolkar

Senior Software Engineer at Wolters Kluwer Tax & Accounting

8 年

Why is the code not visible?

回复

要查看或添加评论,请登录

Shoeb Sayyed的更多文章

社区洞察

其他会员也浏览了