Using a strategy pattern and a command pattern
Asked Answered
W

7

125

Both design patterns encapsulate an algorithm and decouple implementation details from their calling classes. The only difference I can discern is that the Strategy pattern takes in parameters for execution, while the Command pattern doesn't.

It seems to me that the command pattern requires all information for execution to be available when it is created, and it is able to delay its calling (perhaps as part of a script).

What determinations guide whether to use one pattern or the other?

Warwickshire answered 7/10, 2010 at 16:22 Comment(0)
T
99

I'm including an encapsulation hierarchy table of several of the GoF design patterns to help explain the differences between these two patterns. Hopefully it better illustrates what each encapsulates so my explanation makes more sense.

First off, the hierarchy lists the scope for which a given pattern is applicable, or the appropriate pattern to use to encapsulate some level of detail, depending on which side of the table you start at.

design pattern encapsulation hierarchy table

As you can see from the table, a Strategy Pattern object hides details of an algorithm's implementation, so the use of a different strategy object will perform the same functionality but in a different way. Each strategy object might be optimized for a particular factor or operate on some other parameter; and, through the use of a common interface, the context can safely work with either.

The Command Pattern encapsulates a much smaller level of detail than an algorithm. It encodes the details needed to send a message to an object: receiver, selector and arguments. The benefit to objectifying such a tiny part of the process execution is that such messages can be invoked along different points of time or location in a general way without having to hard-code its details. It allows messages to be invoked one or more times, or passed along to different parts of the system or multiple systems without requiring the details of a specific invocation to be known before execution.

As is typical for design patterns, they do not require all implementations to be identical in detail to bear the pattern name. Details can vary in implementation and in what data is encoded in the object versus as method arguments.

Tourneur answered 9/10, 2010 at 9:55 Comment(2)
So if I had a system that filtered results with a "filter pipeline" and used delegates as filters (where each of the filter's algorithms would be encapsulated within a function) would that be considered a Command pattern? In this case I see the delegate for the filter function as providing a contract of sorts for what each filter must adhere to in terms of input and output.Burletta
@KTF, no. The Command pattern employs an object which has most (if not all) the info needed (eg, receiver, selector, arguments) to invoke an object's method. It's a simplistic pattern which can be used in other design patterns such as Chain of Responsibility, Collection and the Pipeline pattern you describe. The "contract of sorts" provided by your delegates is another pattern, Interface.Tourneur
C
53

Strategies encapsulate algorithms. Commands separate the sender from the receiver of a request, they turn a request into an object.

If it's an algorithm, how something will be done, use a Strategy. If you need to separate the call of a method from its execution use a Command. Commands are often used when you queue up messages for later use, like a task or a transaction.

Choppy answered 7/10, 2010 at 16:45 Comment(1)
that made sense en.wikipedia.org/wiki/Command_Pattern client and invoker are tied, but at the same time, they dont know about each other!Tomboy
W
28

Answering a very old question. (is anybody seeing lastest answers instead of most voted?)

It is a valid confusion to have because of the similarities. Both Strategy and Command patterns utilize encapsulation. But that does not make them same.

The key difference is to understand what is encapsulated. The OO principle, both patterns depend on, is Encapsulate what varies.

In case of strategy, what varies is algorithm. For example, one strategy object knows how to output to XML file, while the other outputs to, say, JSON. Different algorithms are kept (encapsulated) in different classes. It is as simple as that.

In case of command, what varies is the request itself. Request may come from File Menu > Delete or Right Click > Context Menu > Delete or Just Delete Button pressed. All three cases can generate 3 command objects of same type. These command objects only represent 3 requests for deletion; not deletion algorithm. Since requests are bunch of objects now, we could manage them easily. Suddenly it become trivial to provide functionality such as undo or redo.

It doesn't matter how command implements the requested logic. On calling execute(), it may implement an algorithm to trigger deletion or it can even delegate it to other objects, may even delegate to a strategy. It is only implementation detail of the command pattern. This is why it is named as command though it is not a polite way to request :--)

Contrast it with strategy; this pattern is only concerned with the actual logic that gets executed. If we do that, it helps to achieve different combinations of behaviors with minimal set of classes, thus preventing class explosion.

I think, Command helps us to broaden our understanding of encapsulation while Strategy provides natural use of encapsulation and polymorphism.

Waverley answered 13/8, 2014 at 14:38 Comment(0)
E
15

The way that I look at it is that you have multiple ways of doing the same thing, each of those is a strategy, and something at runtime determines which strategy gets executed.

Maybe first try StrategyOne, if the results aren't good enough, try StrategyTwo...

Commands are bound to distinct things that need to happen like TryToWalkAcrossTheRoomCommand. This command will be fired whenever some object should try to walk across the room, but inside it, it might try StrategyOne and StrategyTwo for trying to walk across the room.

Mark

Embryogeny answered 7/10, 2010 at 16:35 Comment(2)
RE: "multiple ways of doing the same thing" - That seems to conflict with some of the common examples of Strategy. Specifically the ones where there are implementation classes that do addition, subtraction, multiplication, etc. Maybe those are not good examples?Alec
@JoshuaDavis all these "substratagies" are special cases of one strategy: arithmetical operation. they have common arguments (2 operands) and produce one value as result. pretty much doing the same (being blackboxes) thing their own different way, depending on implementation. so i see no conflict here, but, quite the opposite: nice example =)Orianna
M
7

I might be wrong in my opinion, but I treat the command as function-to-execute, or reaction. There should be at least two players: the one who requests the action, and the one who executes the action. GUI is typical example for command pattern:

  • All buttons on application toolbar are associated with some action.
  • Button is the executor in this case.
  • Action is the command in this case.

The command is usually bounded to some scope or business area, but not necessary: you may have commands that issue a bill, start a rocket or remove a file implementing the same interface (e.g. single execute() method) within one application. Often commands are self-containing, so they don't need anything from the executor to process the task they are intend to (all necessary information is given at construction time), sometimes commands are context-sensitive and should be able to discover this context (Backspace command should know the caret position in the text to correctly remove the previous character; Rollback command should discover the current transaction to rollback; ...).

The strategy is a bit different: it is more bound to some area. The strategy may define a rule to format a date (in UTC? locale specific?) ("date formatter" strategy) or to calculate a square for a geometric figure ("square calculator" strategy). Strategies are in this sense flyweight objects, that take something as input ("date", "figure", ...) and make some decision on its basis. Perhaps not the best, but good example of strategy is one connected with javax.xml.transform.Source interface: depending on whether the passed object is DOMSource or SAXSource or StreamSource the strategy (= XSLT transformer in this case) will apply different rules to process it. The implementation can be a simple switch or involve Chain of responsibility pattern.

But indeed there is something in common between these two patterns: commands and strategies encapsulate algorithms within the same semantic area.

Mefford answered 7/10, 2010 at 16:53 Comment(3)
I treat the command as a callback function, or reaction. There should be at least two players: one who requests the action, and one who executes... - I understand what you're trying to say, but I'd shy away from using the word 'callback', because often the word 'callback' implies an asynchronous invocation and you don't need to to be making asynchronous invocations for the command pattern to be useful. Case in point: Microsoft Word. Toolbar button clicks and shortcut key presses do not invoke asynchronous commands, but we can appreciate how to the command pattern would be useful in this caseShortening
I agree, although as Jim said I would edit to remove reference to callback.Donaghue
Thanks, I have made some extensions. Let me know, if you agree/disagree.Mefford
A
5

Command:

Command pattern build a framework for Command , which decouples the object that invokes the operation from the one that knows how to perform it

Workflow:

Client calls Invoker => Invoker calls ConcreteCommand => ConcreteCommand calls Receiver method, which implements abstract Command method.

Advantage : Client is not impacted changes in Command and Receiver. Invoker provide loose coupling between Client and Receiver. You can run multiple commands with same Invoker.

Command pattern allows you to execute a command on different Receivers by using same Invoker. Invoker is unaware of type of Receiver

You can use Command pattern to

  1. Decouple the invoker & receiver of command
  2. Implement callback mechanism

java.lang.Thread is one good implementation of Command pattern. You can treat Thread as invoker & class implementing Runnable as ConcreteCommonad/Receiver and run() method as Command.

Strategy:

Strategy pattern is very simple to understand. Use this pattern when

You have multiple implementations for an algorithm and implementation of algorithm can change at run time depending on particular conditions.

Take an example of Airline booking system's Fare component

Airlines would like to offer different Fares during different time periods - Peak and Off Peak months. During Off peak travel days, it would like to stimulate the demand by offering attractive discounts.

Key takeaways of Strategy pattern:

  1. It's used to switch between family of algorithms
  2. It changes the behavior of the object at run time

Related posts with code examples:

Using Command Design pattern

Real World Example of the Strategy Pattern

Accumulate answered 26/1, 2016 at 17:20 Comment(0)
S
0

For me, the difference is one of intent. The implementations of both patterns are pretty similar, but have different purposes:

  • For a Strategy, the component using the object knows what the object does (and will use it to perform a part of its own work), but it doesn't care how it does it.

  • For a Command, the component using the object knows neither what the Command does nor how it does it - it just knows how to invoke it. The caller's task is just to run the command - the processing carried out by the Command doesn't form part of the caller's core work.

This is the difference - does the object using the component actually know or care about what the component does? Most of the time this can be determined based on whether the pattern object returns a value to its invoker. If the invoker cares about what the pattern object does then it will probably want it to return something and it will be a Strategy. If it doesn't care about any return value it is probably a Command (note, something like a Java Callable is still a Command because, although it returns a value, the caller doesn't care about the value - it just passes it back to whatever originally supplied the Command).

Shylashylock answered 5/2, 2016 at 14:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.