Skip to content

Commit 7d1ad9d

Browse files
author
Badacadabra
committed
Add Chain of Responsibility (ES5 + ES6 + CoffeeScript + TypeScript)
1 parent a4ce851 commit 7d1ad9d

File tree

7 files changed

+259
-0
lines changed

7 files changed

+259
-0
lines changed
Binary file not shown.
Loading
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Synopsis
2+
3+
Imagine a long relay race with athletes from different sports. This race could involve several teams composed each time of a racewalker, a runner and a swimmer.
4+
5+
# Problem
6+
7+
Each sport has its own rules and each athlete will participate differently. So we cannot just evaluate the role of each athlete in the same way, even though the objective is the same for everyone within a team: the gold medal. A swimmer and a runner are both athletes, but a swimmer swims whereas a runner runs... Here we could say that each team member handles a part of the initial request which is to win the race.
8+
9+
Moreover, this is a relay race, not an individual one. Each athlete must know the next relay where another athlete will wait for the baton before to start.
10+
11+
# Solution
12+
13+
Everytime a request should be handled by multiple (and complementary) processing units, the Chain of Responsibility pattern seems ideal. In this case, this pattern requires:
14+
15+
* An abstract representation of a racer (abstract class or interface)
16+
* Concrete racers (Walker, Runner, Swimmer)
17+
* Composition because each racer "class" must have a reference to the next relay (except for the last athlete who crosses the finish line)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# ==============================
2+
# ABSTRACT RACER
3+
# ==============================
4+
5+
class Racer
6+
constructor: ->
7+
throw new Error "You cannot instantiate an abstract class!" if @constructor is Racer
8+
9+
go: ->
10+
res = ""
11+
if @nextRelay? then res += @nextRelay.go() else res += ""
12+
res
13+
14+
setNextRelay: (relay) ->
15+
@nextRelay = relay
16+
17+
# ==============================
18+
# CONCRETE RACERS
19+
# ==============================
20+
21+
class Walker extends Racer
22+
go: ->
23+
"Walker: go!\n#{super}"
24+
25+
class Runner extends Racer
26+
go: ->
27+
"Runner: go!\n#{super}"
28+
29+
class Swimmer extends Racer
30+
go: ->
31+
"Swimmer: go!\n#{super}"
32+
33+
# ==============================
34+
# CLIENT CODE
35+
# ==============================
36+
37+
walker = new Walker
38+
runner = new Runner
39+
swimmer = new Swimmer
40+
41+
walker.setNextRelay runner
42+
runner.setNextRelay swimmer
43+
44+
console.log walker.go()
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// ==============================
2+
// ABSTRACT RACER
3+
// ==============================
4+
5+
abstract class Racer {
6+
protected nextRelay: Racer;
7+
8+
public go(): string {
9+
var res = "";
10+
if (this.nextRelay === undefined) {
11+
res += "";
12+
} else {
13+
res += this.nextRelay.go();
14+
}
15+
return res;
16+
}
17+
18+
public setNextRelay(relay: Racer): void {
19+
this.nextRelay = relay;
20+
}
21+
}
22+
23+
// ==============================
24+
// CONCRETE RACERS
25+
// ==============================
26+
27+
class Walker extends Racer {
28+
public go(): string {
29+
return `Walker: go!\n${super.go()}`;
30+
}
31+
}
32+
33+
class Runner extends Racer {
34+
public go(): string {
35+
return `Runner: go!\n${super.go()}`;
36+
}
37+
}
38+
39+
class Swimmer extends Racer {
40+
public go(): string {
41+
return `Swimmer: go!\n${super.go()}`;
42+
}
43+
}
44+
45+
// ==============================
46+
// CLIENT CODE
47+
// ==============================
48+
49+
let walker: Racer = new Walker(),
50+
runner: Racer = new Runner(),
51+
swimmer: Racer = new Swimmer();
52+
53+
walker.setNextRelay(runner);
54+
runner.setNextRelay(swimmer);
55+
56+
console.log(walker.go());
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
'use strict';
2+
3+
// ==============================
4+
// ABSTRACT RACER
5+
// ==============================
6+
7+
var Racer = (function() {
8+
function Racer() {
9+
if (this.constructor === Racer) {
10+
throw new Error("You cannot instantiate an abstract class!");
11+
}
12+
}
13+
14+
Racer.prototype.go = function () {
15+
var res = "";
16+
if (this.nextRelay === undefined) {
17+
res += "";
18+
} else {
19+
res += this.nextRelay.go();
20+
}
21+
return res;
22+
};
23+
24+
Racer.prototype.setNextRelay = function (relay) {
25+
this.nextRelay = relay;
26+
};
27+
28+
return Racer;
29+
})();
30+
31+
// ==============================
32+
// CONCRETE RACERS
33+
// ==============================
34+
35+
var Walker = (function () {
36+
function Walker() {}
37+
Walker.prototype = Object.create(Racer.prototype);
38+
Walker.prototype.constructor = Walker;
39+
40+
Walker.prototype.go = function () {
41+
return "Walker: go!\n" + Racer.prototype.go.call(this);
42+
};
43+
44+
return Walker;
45+
})();
46+
47+
var Runner = (function () {
48+
function Runner() {}
49+
Runner.prototype = Object.create(Racer.prototype);
50+
Runner.prototype.constructor = Runner;
51+
52+
Runner.prototype.go = function () {
53+
return "Runner: go!\n" + Racer.prototype.go.call(this);
54+
};
55+
56+
return Runner;
57+
})();
58+
59+
var Swimmer = (function () {
60+
function Swimmer() {}
61+
Swimmer.prototype = Object.create(Racer.prototype);
62+
Swimmer.prototype.constructor = Swimmer;
63+
64+
Swimmer.prototype.go = function () {
65+
return "Swimmer: go!\n" + Racer.prototype.go.call(this);
66+
};
67+
68+
return Swimmer;
69+
})();
70+
71+
// ==============================
72+
// CLIENT CODE
73+
// ==============================
74+
75+
var walker = new Walker(),
76+
runner = new Runner(),
77+
swimmer = new Swimmer();
78+
79+
walker.setNextRelay(runner);
80+
runner.setNextRelay(swimmer);
81+
82+
console.log(walker.go());
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// ==============================
2+
// ABSTRACT RACER
3+
// ==============================
4+
5+
class Racer {
6+
constructor() {
7+
if (new.target !== undefined) {
8+
throw new Error("You cannot instantiate an abstract class!");
9+
}
10+
}
11+
12+
go() {
13+
let res = "";
14+
if (this.nextRelay === undefined) {
15+
res += "";
16+
} else {
17+
res += this.nextRelay.go();
18+
}
19+
return res;
20+
}
21+
22+
setNextRelay(relay) {
23+
this.nextRelay = relay;
24+
}
25+
}
26+
27+
// ==============================
28+
// CONCRETE RACERS
29+
// ==============================
30+
31+
class Walker extends Racer {
32+
go() {
33+
return `Walker: go!\n${super.go()}`;
34+
}
35+
}
36+
37+
class Runner extends Racer {
38+
go() {
39+
return `Runner: go!\n${super.go()}`;
40+
}
41+
}
42+
43+
class Swimmer extends Racer {
44+
go() {
45+
return `Swimmer: go!\n${super.go()}`;
46+
}
47+
}
48+
49+
// ==============================
50+
// CLIENT CODE
51+
// ==============================
52+
53+
let walker = new Walker(),
54+
runner = new Runner(),
55+
swimmer = new Swimmer();
56+
57+
walker.setNextRelay(runner);
58+
runner.setNextRelay(swimmer);
59+
60+
console.log(walker.go());

0 commit comments

Comments
 (0)