Search code examples
model-view-controllerdesign-patternsobserver-patterncompositestrategy-pattern

Is the relationship between a View and a Controller in MVC really just a Strategy pattern?


The Gang of Four book states the following:

[...] The main relationships in MVC are given by the Observer, Composite and Strategy design patterns.

The best example of this I could find was this github repo, which shows the following class diagram:

enter image description here

I'm particularly interested in the Strategy part of the MVC, where the following holds:

MVC Name GoF Name
View Context
Controller Strategy
ConcreteController ConcreteStrategy

Regarding the relationship between View and Controller, The book Head First Design Patterns states the following:

The controller may also ask the view to change. When the controller receives an action from the view, it may need to tell the view to change as a result. For example, the controller could enable or disable certain buttons or menu items in the interface

It also shows an example where the ConcreteController equivalent BeatController) defines an additional association with the ConcreteView equivalent (DJView):

package headfirst.designpatterns.combined.djview;
  
public class BeatController implements ControllerInterface {
    BeatModelInterface model;
    DJView view;
   
    // BeatController implementation
}

This association is not present in the Strategy pattern, which only has an arrow going from Context to Strategy (and not the other way round). Furthermore, I've seen examples online which also define this association going from the controller to back to the view:

Is the relationship between Controller and View really only a strategy? If not what is it?


Solution

  • Yes, it's really only a strategy. The relationship between Context and Strategy can be complex, and the GoF book addresses it in several places.

    Strategy and Context interact to implement the chosen algorithm. A context may pass all data required by the algorithm to the strategy when the algorithm is called. Alternatively, the context can pass itself as an argument to Strategy operations. That lets the strategy call back on the context as required. --page 317

    As indicated here, a dependency from Strategy to Context is optional. In the GoF book, UML diagrams generally omit optional relationships for simplicity. Note in the case where Strategy is aware of its Context the dependency would be on the abstraction rather than a ConcreteContext. Cyclic dependencies between concrete classes are generally a bad idea.

    Designing the relationship(s) between Context and Strategy requires some thought.

    The Strategy and Context interfaces must give a ConcreteStrategy efficient access to any data it needs from a context, and vice versa.

    One approach is to have Context pass data in parameters to Strategy operations—in other words, take the data to the strategy. This keeps Strategy and Context decoupled. On the other hand, Context might pass data the Strategy doesn't need.

    Another technique has a context pass itself as an argument, and the strategy requests data from the context explicitly. Alternatively, the strategy can store a reference to its context, eliminating the need to pass anything at all. Either way, the strategy can request exactly what it needs. But now Context must define a more elaborate interface to its data, which couples Strategy and Context more closely.

    The needs of the particular algorithm and its data requirements will determine the best technique. --page 319