Click here to Skip to main content
Click here to Skip to main content

Strategy

, 13 Oct 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
StrategyThe Strategy design pattern allows you to use multiple algorithms interchangeably.  One reason you might use a Strategy Pattern is to

Editorial Note

This articles was originally at wiki.asp.net but has now been given a new home on CodeProject. Editing rights for this article has been set at Bronze or above, so please go in and edit and update this article to keep it fresh and relevant.

Strategy

The Strategy design pattern allows you to use multiple algorithms interchangeably. 

One reason you might use a Strategy Pattern is to simplify an overly complex algorithm. Sometimes, as an algorithm evolves to handle more and more situations, it can become very complex and difficult to maintain. Breaking these complex algorithms down into smaller more manageable algorithms might make your code more readable and more easily maintained.  As a simple example of how to implement the Strategy Pattern consider the following scenario.

A software system uses a single authorization checking class to determine access rights within the system.  Access rights will be different for Anonymous users, Logged-In users and System Administrators.

While we could certainly handle these 3 different access levels within a single class, but what if a fourth type of access level were to be added and perhaps a fifth? Let's break out each of the access checks into its own Strategy object that we can use interchangeably based on what type of user is logged into our system.

First, we need to define an Interface that all of our Strategy classes will implement.  It is by implementing this Interface that our Strategy classes will be able to be used interchangeably.

Public Interface IAuthorityCheck
    Function IsAuthorized(ByVal resource As Object) As Boolean
End Interface 

With a simple interface defined, we can now create any number of different classes that will implement that interface and perform our security checks for us.  Here are 3 examples that represent our Strategy classes.

First, for our Anonymous users, we create a security Strategy class that always returns False.

Public Class AnonymousSecurityCheckStrategy
    Implements IAuthorityCheck

    Public Function IsAuthorized(ByVal resource As Object) As Boolean Implements IAuthorityCheck.IsAuthorized
        'when checking access rights, anonymous users will
        'always be denied access to all resources
        Return False
    End Function
End Class

Next we have our Logged-In users.  They will need a Strategy too to determine their access rights.

Public Class StandardSecurityCheckStrategy
    Implements IAuthorityCheck

    Public Function IsAuthorized(ByVal resource As Object) As Boolean Implements IAuthorityCheck.IsAuthorized
        'based on the current users credentials
        'examine the object and determine if the user is allowed to access it
        Dim result As Boolean = PerformSomeApplicationSpecificSecurityChecks(resource)
        Return result
    End Function
End Class

And finally, we have our System Administrators.  They can access everything so they get a Strategy that always returns True.

Public Class SysAdminSecurityCheckStrategy
    Implements IAuthorityCheck

    Public Function IsAuthorized(ByVal resource As Object) As Boolean Implements IAuthorityCheck.IsAuthorized
        'The System Administrator will be granted access to all secure resources
        Return True
    End Function
End Class

Now, all we need to do is select one of these Strategy objects at runtime and call the IsAuthorized method.  In order to use these classes interchangeably, we will code against the Interface IAuthorithyCheck and not against that actual concrete class types.

One method for selecting a particular strategy could be to use a Factory.  The Factory would encapsulate all the necessary logic for determining which of our various Strategy classes is the correct one to use.  For example:

Public Class AuthorizationStrategyFactory
    'To avoid the need to repeat the logic required to select the correct Strategy object
    'we will encapsulate that logic in a small Factory class
    Public Shared Function GetAuthorizationStrategy() As IAuthorityCheck
        'This method returns 1 of 3 different algorithms for performing authorizations

        'sysadmins gets the Strategy object that always allows access
        If currentUserObject.IsInRole("sysadmin") Then Return New SysAdminSecurityCheckStrategy

        If currentUserObject.LoggedIn = True Then
            'Logged in users (non-sysadmin) get a Strategy object that performs various security checks
            Return New StandardSecurityCheckStrategy
        Else
            'All other users are considered Anonymous
            'These users are given a Strategy object that always disallows access
            Return New AnonymousSecurityCheckStrategy
        End If
    End Function
End Class

With the Strategy objects in place and a Factory to create the correct Strategy object for us, it becomes simple to perform the authorization check

'coding against the Interface we created
Dim authorityCheck As IAuthorityCheck

'ask the Factory for the Strategy object
authorityCheck = AuthorizationStrategyFactory.GetAuthorizationStrategy()

'at this point we have been returned 1 of the 3 strategy objects
'we do not know which one, and we do not need to know which one

'perform authorization check
If authorityCheck.IsAuthorized(someResourceObject) = False Then
    'abort - user not authorized
Else
    'proceed - user was authorized
End If

Now if the time comes for a fourth type of access to be needed (JuniorSysAdminEverythingButPayrollAccess), we can create a new Strategy class that implements our Interface and contains the specific algorithm appropriate for the new security check.  Then we would modify the Factory class to return that new Strategy object when it was appropriate to do so.  The last little bit of code that is calling the IsAuthorized method does not need to change at all.

The example here was perhaps a bit contrived, but I hope that it illustrates the mechanics behind implementing the Strategy Pattern.

Also, note that the Provider Model introduced in ASP.NET 2.0 is based on strategy design pattern.

Example: Strategy Design Patterns in C#.

1.  GoAlgorithm (Interface)

namespace DesignPatterns.StrategyDP {
 
interface GoAlgorithm {
  
             void go();
   }
2. GoByFlyingAlgorithm (Class)
class GoByFlyingAlgorithm: GoAlgorithm {

        public void go() {

            Console.WriteLine("Now I'm Flying"); 

        }

    }
3. GoByDrivingAlgorithm (Class)
class GoByDrivingAlgorithm: GoAlgorithm {
        
     public void go() {

            Console.WriteLine("Now I'm Driving."); 

        }

    } 

You can define more Alorithm's like "GoByMotorBikeAlgoritm" etc.

class GoByMotorBikeAlgoritm: GoAlgorithm {

     public void go() {

             Console.WriteLine("Now I'm Riding");         

         }
}

4. Vehicle (Abstract Class)

abstract class Vehicle {
 
        private GoAlgorithm goAlgorithml;

        public void setAlgorithm(GoAlgorithm Algorithm_Name) {
  
            goAlgorithml = Algorithm_Name;
        }

        public void go() {
  
            goAlgorithml.go();
   
        }
    }

5. Type of Vehicle Like 'Car', 'Vehicle'  and 'Bike' 

class Car: Vehicle {
      
         public  Car() {
            setAlgorithm(new GoByDrivingAlgorithm());
        }

    }

class Helicopter:Vehicle {

        public Helicopter() {
  
            setAlgorithm(new GoByFlyingAlgorithm());
   
        }

    }

class Bike:Vehicle {

        public Helicopter() {
  
            setAlgorithm(new GoByMotorBikeAlgoritm());
   
        }

    }

6. Main

 class Program {
       
  static void Main(string[] args) {
           
   /* Strategy Design Patterns*/
           
            Car F1car = new Car();
            Helicopter Choper = new Helicopter();
            Bike HeroHonda = new Bike();

            F1car.go();
            Choper.go();
            HeroHonda.go(); 

        }
    }

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

ASP.NET Community

United States United States
The ASP.NET Wiki was started by Scott Hanselman in February of 2008. The idea is that folks spend a lot of time trolling the blogs, googlinglive-searching for answers to common "How To" questions. There's piles of fantastic community-created and MSFT-created content out there, but if it's not found by a search engine and the right combination of keywords, it's often lost.
 
The ASP.NET Wiki articles moved to CodeProject in October 2013 and will live on, loved, protected and updated by the community.
Group type: Collaborative Group

247 members


Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web01 | 2.8.141022.1 | Last Updated 13 Oct 2013
Article Copyright 2013 by ASP.NET Community
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid