-
Notifications
You must be signed in to change notification settings - Fork 177
Write page for the Mediator Design Pattern. #91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
4a6f57f
Write page for the Mediator Design Pattern.
391cd09
Add alternative syntax in comment.
530bcb6
Update mediator.md
sang4lv b6c165f
Merge pull request #1 from angelazou/mediator-pattern
f312311
Bring CoffeeScript idiom to conditional statement.
50d4f55
Amount takes only 1 'm'.
2a5dbac
Improve readability.
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
--- | ||
layout: recipe | ||
title: Mediator pattern | ||
chapter: Design patterns | ||
--- | ||
|
||
## Problem | ||
|
||
Imagine 100 airplanes that need to land in airport A, which only accept one airplane landing at a time. | ||
First strategy is to have every plane asking all its peers for landing order. This would be a very time consuming, error prone and quite tedious task. | ||
A better option is to have all airplanes report directly to a control tower, which determines the landing schedule for all airplanes. | ||
Each plane then simply request landing permission from the control tower, and wait for a reply. | ||
With the latter approach, a given plane doesn't need to know about all other planes. | ||
All communication can now be centralized and synchronously broadcasted to all. | ||
|
||
Similarly, we can face this problem when developing software. | ||
When an application is composed of several modules, each module is in charge of its own task but also dependent on the state of other modules. We can have each module listening directly to each of its dependencies, maybe through the Observer pattern, and be notified when a change occur. | ||
The problems with this approach are the same as having airplanes listening to each other. When we have tight coupling between modules, every module has to watch out for its dependencies. | ||
A better approach would be to introduce loose coupling of modules and centralize inter-module communication. With such an approach, each module doesn't need to know about the existence of other modules, but simply listen for events they fire. This is the mediator pattern. | ||
|
||
## Solution | ||
|
||
{% highlight coffeescript %} | ||
|
||
# Our mediator class | ||
class Mediator | ||
|
||
constructor: -> | ||
@channels = {} | ||
|
||
subscribe: (event, context, callback) => | ||
@channels[event] or= [] | ||
@channels[event].push callback.bind context | ||
|
||
publish: (event, args...) => | ||
return false if not @channels[event] | ||
callback(args) for callback in @channels[event] | ||
|
||
wrap: (obj) -> | ||
obj.subscribe = @subscribe | ||
obj.publish = @publish | ||
obj | ||
|
||
# Instantiate our Mediator | ||
MEDIATOR = new Mediator() | ||
|
||
# Module A | ||
class ModuleA | ||
|
||
constructor: -> | ||
MEDIATOR.wrap @ # We add event capabilities to our module | ||
@subscribe 'hello', @, (payload) -> console.log "(ModuleA) Received event 'hello' with payload: #{payload}" | ||
# The 2 lines above could also have been written: | ||
# MEDIATOR.subscribe 'hello', @, (payload) -> console.log "Received event 'hello' with payload: #{payload}" | ||
|
||
# Module B | ||
class ModuleB | ||
|
||
constructor: -> | ||
MEDIATOR.wrap @ # We add event capabilities to our module | ||
@publish 'hello', 'I am moduleB and I just published!' | ||
# The 2 lines above could also have been written: | ||
# MEDIATOR.subscribe 'hello', @, (payload) -> console.log "Received event 'hello' with payload: #{payload}" | ||
|
||
# Instantiate our 2 modules | ||
new ModuleA() | ||
new ModuleB() | ||
|
||
{% endhighlight %} | ||
|
||
|
||
## Discussion | ||
|
||
As you can see we now have inter-module communication without having modules looking out for their dependencies. Hence, ModuleA won't fail if ModuleB isn't there and vice-versa. | ||
Such an approach makes a lot of sense when developing applications such as [Netvibes](http://netvibes.com), [Google Ig](http://google.com/ig) or [Chartbeat](https://chartbeat.com/) dashboards. | ||
|
||
The `MEDIATOR.wrap` step could also be abstracted into a parent class for convenience. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean you want to revert line 51 to
if req.status in [200, 304]
?Please see #discussion-diff-6180754 as for why we used the
if req.status in successResultCodes
syntax.