Differences between Strategy Pattern and Inheritance
Asked Answered
J

4

20

There is a same concept for Strategy Pattern and Inheritance, so I can implement Strategy Pattern with Inheritance that sounds it is simpler and cleaner than Strategy Pattern.

Startegy Pattern:

class IBase
{
public:
    virtual void processAction(void *data) = 0; // pure virtual
}

class Worker: public IBase
{
public:
    virtual void processAction(void *data)
    {
        // define logic
    }
}

Inheritance:

class Base
{
public:
    virtual void processAction(void *data) {}
}

class Worker: public Base
{
public:
    virtual void processAction(void *data) override
    {
        // define logic
    }
}

My question is what is the difference between them? or when should I use Strategy Pattern or Inheritance?

Link: Strategy Pattern

Juxon answered 7/9, 2014 at 12:42 Comment(0)
A
38

Imagine you design a Cache. The cache can have options regarding

  • eviction policy (LIFO, FIFO, LRU)
  • expiration policy (after read, after write)
  • maximum size (number of elements, memory usage)

Now imagine you want to let the user of your cache choose any of these options, and you use inheritance. You'll need 3 * 2 * 2 = 12 different classes:

  • LifoAfterReadNumberOfElementsBasedCache,
  • LifoAfterReadMemoryBasedCache,
  • etc.

Each of the 4 LifoXxx classes will have to implement the same algorithm to implement the LIFO strategy. Same for the other ones.

Implement it with the strategy pattern instead of inheritance, and you'll have a single Cache class, and 7 strategy classes (one for each strategy), that you can combine however you want, and without code duplication.

And you can also let the user of your Cache define its own strategy, that you haven't anticipated, and let him combine it with other strategies without needing to create a whole lot of new subclasses.

Affectation answered 7/9, 2014 at 12:55 Comment(3)
once code compiles then run, I can't understand that how can we change behaviour of object by changing the implementation of interface method at run-time?Juxon
cache.useEvictionStrategy(new LifoStrategy());Affectation
@Reza, also take a look at State pattern, it gives an example of how idea of strategy can be evolved further. Given a field of IStrategy type, you can during runtime set different values, according to events or other logic. strategyField = new AStrategy(), strategyField = new BStrategy(), where AStrategy, BStrategy implement IStrategy. Thus it will change behaivor in runtime. But compiled classes of strategies and strategy-holder won't change.Hammerskjold
H
9

Strategy is a pattern of OOP and Inheritance is a principle of OOP. Strategy is implemented using (or to support) Inheritance (actually, interface generalization).

Inheritance

  • Inheritance is used to achieve all benefits of OOP (it eventually leads to better readbility\maintainability\structure of code).
  • Inheritance is used to form many other patterns, not only Strategy
  • Inheritance is sometimes a limitation because of its static compile-time nature

Strategy

  • Strategy assumes to have different implementations which can be replaced in runtime (or configured in a flexible way). So, your first example is not strategy as well.
  • In general, composition (which is implemented by Strategy) as a way of logic reuse is preferred over inheritance. At first, it provided dynamic polymorphism. At second, it has less implementation limitations like multi-class inheritance, etc.
  • Strategy corresponds to "some changeable algorithm" in terms of DDD, thus has real impact on domain modelling.
  • Strategy, as a pattern itself, provides a language ("pattern language") for communication between developers.

Moreover, according to your example:

  • Base abstract class and interface have two different semantics, thus inheritance in your example have different semantics too. First is about implementation of public contract. Second is about generalization as an extraction of common properties and methods.
Hammerskjold answered 7/9, 2014 at 12:58 Comment(0)
S
7

The answer is in the Wikipedia article you linked in your question.

The strategy pattern uses composition instead of inheritance. In the strategy pattern, behaviors are defined as separate interfaces and specific classes that implement these interfaces. This allows better decoupling between the behavior and the class that uses the behavior. The behavior can be changed without breaking the classes that use it, and the classes can switch between behaviors by changing the specific implementation used without requiring any significant code changes. Behaviors can also be changed at run-time as well as at design-time.

If your situation is simple and static, you certainly can use inheritance, but using Strategy allows you to better decouple complex code and allows simple switching between implementations of the strategy, even at run-time.

Examples may help. There are some good ones in the answers to this related question as well as in the other answers to your question.

A very real situation where you want the ability to change strategy at run-time is in sorting. The sort order can be varied by a strategy (commonly called a Comparator), and you can have multiple implementations of the strategy and mechanisms for the user of your program to change them.

Senaidasenalda answered 7/9, 2014 at 12:50 Comment(0)
C
1

If we are talking about Java, you can consider also the “Composition over inheritance” approach from Effective Java. This will help you with the method invocation, because inheritance violates encapsulation (in general perspective). By choosing composition you can extend your abstraction even further, because it provides you with the ground for Service instance you need.

Claustral answered 8/9, 2014 at 12:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.