The Strategy Pattern

04.04.07

    The strategy pattern is intended to provide a means to define a family of algorithms, encapsulate each one as an object, and make them interchangeable. What does this mean?
    From my understanding of the strategy pattern, you are separating the behavior from an object with the use of an interface. The interface defines the family of algorithms and you encapsulate each behavior with a class that implements this interface. With this use of the interface contained in the class you have the ability to reference different behaviors at runtime.
    To better understand this I created a simple app that is a form with a button. When this button is clicked it uses Reflection to load a .dll that contains a class that defines the behavior of the button.



The first thing I did to implement the strategy pattern was to create my interface that defines my family of behaviors/Algorithms.
namespace Patterns.Strategy.PluginInterface
{
    public interface ICrazyBehavior
    {
        void GoCrazy();
    }
}

In order to assign a concrete behavior I created a class that implemented this interface.

using Patterns.Strategy.PluginInterface;
using System.Windows.Forms;
namespace MyUsefullPlugin
{
    class MyUseFullPlugin : ICrazyBehavior
    {
        public void GoCrazy()
        {
            MessageBox.Show("This Plug-in is out of controll");
        }
    }
}


Finally I wrote the class that contains the interface and all other content I needed.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using Patterns.Strategy.PluginInterface;
namespace Patterns.Strategy
{
    public partial class PlugableStrategy : Form
    {
        private List<ICrazyBehavior> _crazyBehavior = new List<ICrazyBehavior>();
        public PlugableStrategy()
        {
            InitializeComponent();
        }
        private void btnGoCrazy_Click(object sender, EventArgs e)
        {
            GetPlugins();
            foreach (ICrazyBehavior thisBehavior in _crazyBehavior)
            {
                thisBehavior.GoCrazy();
            }
        }
        // Messy Reflection stuff
        private void GetPlugins()
        {
            _crazyBehavior.Clear();
            string path = Application.StartupPath + "/Plugins";
            string[] files = Directory.GetFiles(path, "*.dll");
            foreach (string file in files)
            {
                try
                {
                    Assembly asm = Assembly.LoadFrom(file);
                    Type[] types = asm.GetTypes();
                    foreach (Type type in types)
                    {
                        Type[] interfaces = type.GetInterfaces();
                        foreach (Type currentInterface in interfaces)
                        {
                            if (currentInterface.Name == "ICrazyBehavior")
                            {
                                if (currentInterface.Namespace == "Patterns.Strategy.PluginInterface")
                                {
                                    object obj = asm.CreateInstance(type.Namespace + "." + type.Name);
                                    _crazyBehavior.Add((ICrazyBehavior)obj);
                                }
                            }
                        }//interface
                    }//type
                }
                catch (Exception) { }
            }//file
        }
    }
}

So, putting this all together I have my form/class that contains a button when some one clicks this button it calls GetPlugins(). The method GetPlugins() uses Reflection to find any .dlls in the plugins folder that contains the ICrazyBehavior interface with the name space of Patterns.Strategy.PluginInterface. If such thing exists in the folder it creates an instance of this object and adds it to my list of _crazyBehaviors once the list is filled the click event continues, it iterates through the list calling the method GoCrazy().

    Using the strategy pattern allowed me to decouple the context class and its behavior enabling me to implement a very "useful" pluggable application.

The Code:

Patterns.zip (83.64 KB)