0

Strategy pattern decouples the context code and strategies (or algorithm or policy) being used by it. It has an advantage over Template Pattern as it enables dynamic behavior change and uses composition with delegation to achieve it. Below is such example.

public class Context{
    private Policy policy;

    public void setPolicy(Policy policy){
        this.policy = policy;
    }

    public performTask(){
        policy.apply(); // delegate policy apply to separate class
        this.contextualWOrk();
    }
}

public interface Policy{
    void apply();
}

public class PolicyX{
     public void apply(){
         //Policy X implementation
     }
}

public class PolicyY{
     public void apply(){
         //Policy Y implementation
     }
}

Now the Code using above code

public class User{
    public void init(Context context){
         context.setPolicy(new PolicyX());
         context.performTask();
    }
}

Above we see the user code has to know and supply concrete Policy to Context. We can use Creational Pattern like Factory method pattern but still in such a case user code will have to know the concrete Factory class. This requires user code to instantiate and know about existence of such concrete implementations.

To prevent this a simple solution can be having a static method taking input as string or enum and using 'switch-case' or multiple 'if-else' statements deciding which class to instantiate and provide the implementation to user code. But again this violates 'OCP' as in case of addition of a new type will require the code to be modified.

How this can be made to follow principles in simple application (I am not sure may be with some configurations Spring and other frameworks solves such issues).

Any hints or key points to solve this in simple application will be helpful.

nits.kk
  • 5,204
  • 4
  • 33
  • 55
  • 1
    I don't quite understand how user code is supposed to choose a policy **without knowing** of its existance? – yegodm Feb 24 '19 at 17:25
  • Your idea of an enum coupled with the function api will save you using any form of `switch` statement. That being said, `Policy` subclasses seem like they're fairly pure functions, you could probably directly instantiate a single/constant instance of each one for the enum and skip functions entirely. Then simply return that instance. – Rogue Feb 24 '19 at 17:34
  • @Rogue yes it is interesting the case of enum with functions. Using functions inside enum, a layer between user code and object creation can be created. But as enum instance is known to user, it is very much like factory only, – nits.kk Feb 24 '19 at 18:57
  • 1
    Yes but that's like asking someone to build a puzzle without the pieces, sure they might know what a puzzle is or how to do them, but it's pointless without the actual pieces. Similarly you can't use configurable behavior without actually being able to specify the configuration. The enum presents a level of abstraction to a specific behavior without an underlying class. If you want to allow expanding behavior by the user, provide an interface for your strategy and implement it over your enum of default behaviors – Rogue Feb 24 '19 at 19:49
  • @conditional annotation can be used to define Policy(strategy) at run-time. https://javapapers.com/spring/spring-conditional-annotation/ – G.G. Feb 25 '19 at 08:28
  • thanks @G.G yes sure but any app which is not based on spring framework, is there a simple way to achieve this ? – nits.kk Feb 25 '19 at 09:48

1 Answers1

1

This drawback of the Strategy Pattern is mentioned on page 318.

Clients must be aware of different Strategies. The pattern has a potential drawback in that a client must understand how Strategies differ before it can select the appropriate one. Clients might be exposed to implementation issues. Therefore you should use the Strategy pattern only when the variation in behavior is relevant to clients.

As you've noted, the strategy selection mechanism can be hidden behind other layers of code, or moved to a configuration file; but the underlying selection must still be made somewhere. This is simply a drawback of the pattern to be aware of when choosing to apply it.

jaco0646
  • 15,303
  • 7
  • 59
  • 83
  • hmm, thanks for the answer @jaco0646 , I feel sometimes its the user code which knows about the policy (algorithm or strategy) and so it will be concrete policies (not always but most often) written by user code so creating object of concrete strategy classes seems fine. – nits.kk Feb 25 '19 at 09:52