Strategy design pattern is a behavioral type of design pattern that allows to change the algorithm (strategy) to your solution dynamically. Here is a uml diagram of the pattern (Wikipedia Image)

So we have 3 main actors in this design pattern.
- Actor #1: The Strategy: Usually an interface or abstract class that has the signature for the function we want to change dynamically.
- Actor #2: ConcreteStategy: The classes that implement the function that is introduced by Actor #1
- Actor #3: Context: The client that uses actor #1 to call the functions at actor #2
Let’s come up with a few scenarios where we can implement this pattern.
Assume your application has a Notification features, depending on some configuration, this notification could send an email, page somebody, call somebody, log it to the database, log it to the event log etc…
If you don’t separate these different functions from the context, than you will have a huge switch case. Instead you can have an interface INotifyUser with a single SendMessage functionality such as:
1: public INotifyUser
2: { 3: public void Notify(string NotificationMessage)
4: }
This is our actor #2, the strategy. Our next actor could be the concrete strategies, such as the classes that implement this interface.
1: public class SaveToDatabase: INotifyUser
2: { 3: public void Notify(string NotificationMessage)
4: { 5: // Write to database code comes in here
6: }
7: }
8:
9: public class EmailToUser
10: { 11: public void Notify(string NotificationMessage)
12: { 13: //Email to user code comes in here
14: }
15: }
16:
17: public class SMSToUser:INotifyUser
18: { 19: public void Notify(string NotificationMessage)
20: { 21: //SMS code comes in here
22: }
23: }
After we have our strategy, and the concrete classes, all we need is a context that will use the interface to swap the algorithm dynamically. If you are C# developer, you can see a similarity with this pattern and delegates, lambda expressions too.
Our context could be SystemFailure class which has dependency on the interface and call the Notify function. I took the example from Dimecasts.net and modified it so that it fits into my solution.
1: public enum SystemNotifier
2: { 3: SaveToDatabase,
4: EmailToUser,
5: SMSToUser
6: };
7:
8: public class SystemFailureLog
9: { 10: var _Notifiers = new Dictionary<SystemNotifier,INotifyUser>();
11:
12: private void CreateNotifiers(){ 13: _Notifiers.Add(SystemNotifier.SaveToDatabase,new SaveToDatabase());
14: _Notifiers.Add(System.Notifier.EmailToUser,new EmailToUser());
15: _Notifiers.Add(System.Notifier.SMSToUser,new SMSToUser());
16:
17: public SystemFailureLog(){ 18: CreateNotifiers();
19: }
20:
21: public void NotifySystemFailure(SystemNotifier strategy,string message){ 22: _Notifiers[strategy].Notify(message);
23: }
24: }
25:
As you can see, the context, has a dictionary that holds different strategies, and by passing an enum value, you can dynamically change what functionality you will be using.
How can we use this? Imaging, you have a system monitoring tool, and the first time system fails, it uses SystemFailireLog and calls save to database function, the second time system fails, email to user, and maybe third one is sms to user.
public class SystemWatchDog
{
public static int FailureCount = 0;
private SystemFailureLog _FailureLogger = new SystemFailureLog();
public void ReactToSystemFailure()
{
FailureCount = FailureCount++;
if(FailureCount==1)
SystemFailureLog.NotifySystemFailure(SystemNotifier.SaveToDatabase,
String.Format("System failure, restarting at {0}",DateTime.Now);
else if (FailureCount ==2)
SystemFailureLog.NotifySystemFailure(SystemNotifier.EmailToUser,
String.Format("System failure, restarting at {0}",DateTime.Now);
else
SystemFailureLog.NotifySystemFailure(SystemNotifier.SMSToUser,
String.Format("System failure, restarting at {0}",DateTime.Now);
}
}
Have Fun :)
Tags: