Search code examples
design-patternspolymorphismstrategy-pattern

Strategy Pattern Implementation


Following is the structure of my class

public abstract class BaseUser
{
    protected List<Perm> permissions;
    public abstract void AddPerm(Perm perm);
}

public class NormalUser : BaseUser
{
    public override void AddPerm(Perm perm)
    {
        throw new InvalidOperationException("A normal user cant add permissions");
    }
}

public class SpecialUser : BaseUser
{
    public override void AddPerm(Perm perm)
    {
        if(permissions==null) permissions=new List<Perm>();
            this.permissions.Add(perm);
    }
}

class Container
{
    List<BaseUser> users;
}

What is required:

  1. Container will keep both types of users
  2. SpecialUser will have the functionality of add permissions - Done
  3. Normal User will not be allowed add permissions - Done

    I have chosen strategy pattern to achieve above

    The thing I am not able to achieve is

  4. Both Types of users will be hydrated from the Database (The users will be initialized with list of default permissions)

Am I right in choosing this pattern in this situation? If yes then how do I address requirement 4?

Many Thanks, asolvent


Solution

  • The example your provided is not really an instance of the strategy pattern, it is just a method override. The strategy pattern involves a context object and a strategy object. Regardless, I would try to avoid the temptation to apply OOP in all possible places. Instead of inheritance consider using a UserType enum and a simple if statement to support the required behavior. This makes it easier to map to a database and also keeps the code simple:

    enum UserType {
     Normal,
     Special
    }
    
    class User {
    
    public UserType Type { get; set; }  
    
    public override void AddPerm(Perm perm){
      switch (this.Type) {
     // logic goes here
      } 
     }
    } 
    

    This type of problem is a recurring theme in using OOP in enterprise data driven applications and I normally try to keep things as simple as possible. Do you really need to derive a base User type to provide the required functionality? Will it have additional behaviors and properties?