views:

156

answers:

4

I am implementing a few strategies (Strategy Pattern) which have some common behavior and am undecided where the common operations should live.

  • Assuming I 1 context and 3 strategies, some of the operations used in the strategies are shared, some are needed only by 2 others just be 1 of the strategies.
  • There is no member level state shared, therefore the only operations are effectively stateless.
  • The intention of the operations are to support the formatting of state to a file, like a view helper.

Option 1: Make an AbstractStrategy class

  • I'm using Java so this immediately takes away using this feature in the future.
  • Inheritance tends to result. in a ridge structure.
  • Operations would be final.

Option 2: Create a Util class of static helpers

  • Flexible, but feels like a code smell for some reason.
  • Not ridged.

Any recommendations or preferences?

Note the level I am working at is the Strategy level, not the Context level (see wikipedia link).

+1  A: 

There are many ways to achieve this.

  1. Use an abstract class and make the variable parts of the execution into abstract methods => Some strategies would implement all operations (by overriding the abstract methods) while others could skip the optional ones. Note that in this case the optional operations could be empty hook methods rather than abstract methods. That way you avoid the hassle of having to implement these operations as empty methods in the subclass.

  2. Use an actual 'Strategy' interface (with an execute method like in the wikipedia article you pointed to). The client class would then be provided by an implementation of the strategy (could be an anonymous inner class or an actual full blown strategy class).

The first is more straightforward but more rigid: if you have to modify the number of operations (specially the abstract ones), all the subclasses have to be updated.

The second is more flexible but you'll have to find a way to "share" common operations between different strategies either by delegating or using static utility methods.

dimdm
"The second is more flexible but you'll have to find a way to "share" common operations between different strategies either by delegating or using static utility methods." -- Strategy is the level I'm working at and the "common parts" as you say is the problem I'm trying to solve.
JamesC
Are the common parts well suited for small units of business? What I mean by that is: could they be modelled as functions? If so, I suggest encapsulating these operations in small 'operation' classes and reusing those accross strategies.The advantages are testability and reusability in that case.
dimdm
Small units yes, but not across the business. Only applicable for the strategies - so I'm thinking static util package restricted, thoughts?
JamesC
If all you need is stateless logic then package restricted static methods are as good as objects. You loose polymorphism (and the love and support of OO purists ;-) but it's still as testable and reusable.
dimdm
A: 

There is another option in addition to the two that you listed:

It sounds to me that you'd like you some kind of composition where you can pull in only the functionality that you require. Perhaps you could package your operations using the command pattern and then assemble your strategies from these?

Advantages:

  • Strategy inheritance not required.
  • Strategies will not have visibility onto unused/hidden 'shared methods'.
  • No static utility class with a jumble of (possibly) unrelated methods.
  • Simpler to unit test - operations can be tested in isolation.
  • Simple shared strategy class that iterates over operations.

Disadvantages:

  • Additional classes.
  • Operations will have to conform to a common command interface which may be restrictive.
  • Could be overkill for very simple operations - which your formatters may be.
teabot
Strategies are very similar to Commands in this instance so I don't see how I could avoid inheritance because the Commands will still need to share common functions across them if I understand you correctly, how do you propose that to be implemented?
JamesC
I am suggesting that the strategies are composed of commands. Each 'function' is a command instance. You can then simply compose your strategies by picking and choosing appropriate commands.
teabot
+1  A: 

There is one reason... one huge reason... to use a static Util class over an abstract class or interface.

So you can add more methods at a later date.

With an abstract class or interface, any change you make to that class/interface has to be changed in all classes that inherit from it. This is especially problematic if you're writing a public API.

The Java framework has util classes with static methods scattered throughout. The most well known ones are in the java.util package: Collections and Arrays.

R. Bemrose
Good point. I personally think static is the way to go. The functions fit well in to the ViewHelper pattern so over complicating this seems unnecessary.
JamesC
A: 

if it is declared as Abstract, people may guess it's designed for extend. So to declare a private constructor is a better idea.

卢声远 Shengyuan Lu