Java Abstract Class or Static Utility Class Design

2019-03-19 12:40发布

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).

4条回答
欢心
2楼-- · 2019-03-19 13:24

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

查看更多
forever°为你锁心
3楼-- · 2019-03-19 13:29

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.
查看更多
够拽才男人
4楼-- · 2019-03-19 13:41

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.

查看更多
Lonely孤独者°
5楼-- · 2019-03-19 13:42

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.

查看更多
登录 后发表回答