State pattern helps a class to exhibit different behaviors in a different state. Strategy Pattern encapsulates a set of related algorithms and allows the client to use interchangeable behaviors through composition and delegation at runtime.
The factory pattern is a creational pattern while the strategy is a behavioral pattern which means they were created using different approaches. We can solve problems in real life using both approaches but before using them we can check which approach is simpler and more effective to solve our problem.
While the Strategy pattern is meant for behavior, the Bridge pattern is meant for structure. The coupling between the context and the strategies is tighter than the coupling between the abstraction and the implementation in the Bridge pattern.
Honestly, the two patterns are pretty similar in practice, and the defining difference between them tends to vary depending on who you ask. Some popular choices are:
A "classic" implementation would match either State or Strategy for every item on the list, but you do run across hybrids that have mixes of both. Whether a particular one is more State-y or Strategy-y is ultimately a subjective question.
getStatus()
method that will return different statuses based on the
state of the object, but the caller of the method doesn't have to be
coded differently to account for each potential state.The difference simply lies in that they solve different problems:
The constructs for achieving these different goals are however very similar; both patterns are examples of composition with delegation.
Some observations on their advantages:
By using the State pattern the state-holding (context) class is relieved from knowledge of what state or type it is and what states or types that are available. This means that the class adheres to the open-closed design principle (OCP): the class is closed for changes in what states/types there are, but the states/types are open to extensions.
By using the Strategy pattern the algorithm-using (context) class is relieved from knowledge of how to perform a certain task (-- the "algorithm"). This case also creates an adherence to the OCP; the class is closed for changes regarding how to perform this task, but the design is very open to additions of other algorithms for solving this task.
This likely also improves the context class' adherence to the single responsibility principle (SRP). Further the algorithm becomes easily available for reuse by other classes.
Can somebody please explain in layman's terms?
Design patterns are not really "layman" concepts, but I'll try to make it as clear as possible. Any design pattern can be considered in three dimensions:
Let's compare State and Strategy.
State is used in one of two cases [GoF book p. 306]:
- An object's behavior depends on its state, and it must change its behavior at run-time depending on that state.
- Operations have large, multipart conditional statements that depend on the object's state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure. The State pattern puts each branch of the conditional in a separate class. This lets you treat the object's state as an object in its own right that can vary independently from other objects.
If you want to make sure you indeed have the problem the State pattern solves, you should be able to model the states of the object using a finite state machine. You can find an applied example here.
Each state transition is a method in the State interface. This implies that for a design, you have to be pretty certain about state transitions before you apply this pattern. Otherwise, if you add or remove transitions, it will require changing the interface and all the classes that implement it.
I personally haven't found this pattern that useful. You can always implement finite state machines using a lookup table (it's not an OO way, but it works pretty well).
Strategy is used for the following [GoF book p. 316]:
- many related classes differ only in their behavior. Strategies provide a way to configure a class with one of many behaviors.
- you need different variants of an algorithm. For example, you might define algorithms reflecting different space/time trade-offs. Strategies can be used when these variants are implemented as a class hierarchy of algorithms [HO87].
- an algorithm uses data that clients shouldn't know about. Use the Strategy pattern to avoid exposing complex, algorithm-specific data structures.
- a class defines many behaviors, and these appear as multiple conditional statements in its operations. Instead of many conditionals, move related conditional branches into their own Strategy class.
The last case of where to apply Strategy is related to a refactoring known as Replace conditional with polymorphism.
Summary: State and Strategy solve very different problems. If your problem can't be modeled with a finite state machine, then likely State pattern isn't appropriate. If your problem isn't about encapsulating variants of a complex algorithm, then Strategy doesn't apply.
State has the following UML class structure:
Strategy has the following UML class structure:
Summary: in terms of the static structure, these two patterns are mostly identical. In fact, pattern-detecting tools such as this one consider that "the structure of the [...] patterns is identical, prohibiting their distinction by an automatic process (e.g., without referring to conceptual information)."
There can be a major difference, however, if ConcreteStates decide themselves the state transitions (see the "might determine" associations in the diagram above). This results in coupling between concrete states. For example (see the next section), state A determines the transition to state B. If the Context class decides the transition to the next concrete state, these dependencies go away.
As mentioned in the Problem section above, State implies that behavior changes at run-time depending on some state of an object. Therefore, the notion of state transitioning applies, as discussed with the relation of the finite state machine. [GoF] mentions that transitions can either be defined in the ConcreteState subclasses, or in a centralized location (such as a table-based location).
Let's assume a simple finite state machine:
Assuming the subclasses decide the state transition (by returning the next state object), the dynamic looks something like this:
To show the dynamics of Strategy, it's useful to borrow a real example.
Summary: Each pattern uses a polymorphic call to do something depending on the context. In the State pattern, the polymorphic call (transition) often causes a change in the next state. In the Strategy pattern, the polymorphic call does not typically change the context (e.g., paying by credit card once doesn't imply you'll pay by PayPal the next time). Again, the State pattern's dynamics are determined by its corresponding fininte state machine, which (to me) is essential to correct application of this pattern.
The Strategy Pattern involves moving the implementation of an algorithm from a hosting class and putting it in a separate class. This means that host class does not need to provide the implementation of each algorithm itself, which is likely to lead to unclean code.
Sorting algorithms are usually used as an example as they all do the same kind of thing (sort). If each differing sorting algorithm is put into its own class, then the client can easily choose which algorithm to use and the pattern provides an easy way to access it.
The State Pattern involves changing the behaviour of an object when the state of the object changes. This means that the host class does not have provide the implementation of behaviour for all the different states that it can be in. The host class usually encapsulates a class which provides the functionality that is required in a given state, and switches to a different class when the state changes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With