8

To keep classes decoupled I'm using the Mediator Pattern like so:

class Mediator {
  constructor(canvas, selectionBox, undoManager) {
    this.canvas = canvas
    this.selectionBox = selectionBox
    this.undoManager = undoManager
  }

  addText(text) {
    this.canvas.addText(text)
    this.undoManager.captureUndo()
    this.selectionBox.update()
  }

  addImage(image) {
    this.canvas.addImage(image)
    this.undoManager.captureUndo()
    this.selectionBox.update()
  }

  // ... etc
}

as more and more methods are added on the Mediator class, isn't it going to become a God Object?

If that's the case how do I resolve this? Perhaps create sub-mediators that group actions together and use a parent mediator to coordinate them?


(*) For the record I just started using this pattern and I'm not sure I'm doing this correctly.

nicholaswmin
  • 1,869
  • 2
  • 18
  • 36
  • Possible duplicate of [How to apply the single responsibility principle if the program should do a lot of things?](https://softwareengineering.stackexchange.com/questions/356595/how-to-apply-the-single-responsibility-principle-if-the-program-should-do-a-lot) – gnat Apr 20 '18 at 09:33
  • 11
    @gnat You're really trigger happy with the close votes. I'm also (and most importantly) asking how to prevent it from becoming a god object. I appreciate you pointing me to another resource (which did help) but your overzealous attempts at moderation are making me think twice if I would ever get help asking questions in this site. – nicholaswmin Apr 20 '18 at 09:43
  • Your problem is related to too broad name of the class. It should be more specific to narrow number of functions inside. Of course it is a balance between number of classes vs number of methods. I really recommend try to use convention noun + verbal noun (e.g. ImageResizer, ImageTextUpdater). The level of granulation depends on your particular case. – Tomasz Maciejewski Apr 20 '18 at 10:11
  • @kadiii Which class? The mediator? – nicholaswmin Apr 20 '18 at 10:12
  • Yes, the mediator. The mediator class role is to hide complex logic of some operation which require many dependencies. They can be aggregated in logical groups to prevent putting everything into one class. – Tomasz Maciejewski Apr 20 '18 at 10:22
  • @kadiii Oh great, so you're saying I should split up the mediator to "sub-mediators". Care to write up a complete answer for me? – nicholaswmin Apr 20 '18 at 10:23

2 Answers2

6

The role of the Mediator Pattern is to encapsulate communication logic between objects, reducing dependencies between them (reducing coupling).

However, like with any encapsulation if you put everything into one bag you can end up with so called God Object.

Solution for this is to use Single Responsibility Principle and split mediator objects, creating groups around the same behaviour. Practical tip can be to use convention - noun + verbal noun (e.g. ImageResizer, ImageTextUpdater).

It is not an issue of mediator pattern itself but incorrect (too broad) encapsulation in one class.

1

No, your Mediator class does not look like it is becoming a God Object. A class is not a God Object because it has many methods, but because it can interact with nearly all other objects in your system. That is not the case for your Mediator class.

On a side node, the Mediator class looks more like the implementation of the Facade design pattern.
In a correct implementation of the Mediator pattern, the Mediator class would assist in updating the selectionBox when the canvas changes and vice versa. It would typically not be triggered by classes outside the Mediator pattern.

Bart van Ingen Schenau
  • 71,712
  • 20
  • 110
  • 179
  • It can lead to God Object as it is when object *knows too much or does too much*. So if the number of methods grows they need to be split. And definitely generic names like Mediator lead to such a situation. So your sentence "A class is not a God Object because it has many methods, but because it can interact with nearly all other objects" is wrong. – Tomasz Maciejewski Apr 20 '18 at 10:41
  • `In a correct implementation of the Mediator pattern, the Mediator class would assist in updating the selectionBox`, err isn't that the Observer Pattern? – nicholaswmin Apr 20 '18 at 13:45
  • @NicholasKyriakides Yes. However a class can participate in multiple patterns. `Mediator` (rather a bad name) *observes* both the canvas and the selection, and *mediates* the interaction – Caleth Apr 20 '18 at 13:56
  • @Caleth I think you're wrong. A Mediator simply encapsulates how a set of objects interact. There's no mention of observing it's member etc in any definitions of this pattern, at least not any I've read. – nicholaswmin Apr 20 '18 at 16:12
  • @NicholasKyriakides the answer is suggesting *this class* (named `Mediator` because we lack context to suggest a better name) *do those things* – Caleth Apr 20 '18 at 16:21
  • @Caleth How so? My `Mediator` class simply declares methods that are supposed to be called by external (or even internal) code and then it calls the different classes to achieve a goal. Which part in my `Mediator` class is indicating that I'm observing something? – nicholaswmin Apr 20 '18 at 17:21
  • @NicholasKyriakides: The Mediator Pattern makes use of the Observer Pattern. One difference is that in the Observer pattern, you typically have multiple observers connected to a single subject, while in the Mediator pattern, there is one observer (the mediator) that is registered to multiple subjects. – Bart van Ingen Schenau Apr 20 '18 at 19:15
  • Also each design pattern has a typical structure that can be observed in the class diagram and interactions that can be seen in a sequence diagram. If you diagram your code, can you recognize the structure and interactions of the Mediator pattern in it? If not, you have not implemented that pattern. – Bart van Ingen Schenau Apr 20 '18 at 19:18