Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3ddfad1

Browse files
author
Badacadabra
committed
Add Observer (ES5 + ES6 + CoffeeScript + TypeScript)
1 parent 792c910 commit 3ddfad1

File tree

7 files changed

+324
-0
lines changed

7 files changed

+324
-0
lines changed
2.28 KB
Binary file not shown.
15 KB
Loading[フレーム]

‎doc/GoF/Behavioral/Observer/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Synopsis
2+
3+
In the savanna, there are predators like lions or crocodiles and there are preys like gazelles. So lions and crocodiles often attack gazelles.
4+
5+
# Problem
6+
7+
Lions and crocodiles do not attack at any moment. A lion will generally attack if a gazelle is a bit too far from the herd. A crocodile will generally attack if a gazelle is a bit too close to water, especially for drinking.
8+
9+
In programming terms, predators execute some action when a specific event occurs on the preys side. This implies the implementation of an event-handling mechanism in the code, which may be unclear if it is not properly done.
10+
11+
# Solution
12+
13+
The Observer design pattern helps a lot when we have to implement an event-driven system like this. Here this pattern is composed of:
14+
15+
* An abstract representation of preys which are observable objects (abstract class is preferred because each prey may have multiple predators)
16+
* An abstract representation of predators which are observers (abstract class or interface)
17+
* A concrete prey (Gazelle)
18+
* Concrete predators (Lion & Crocodile)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# ==============================
2+
# ABSTRACT OBSERVER
3+
# ==============================
4+
5+
class Predator
6+
constructor: ->
7+
throw new Error "You cannot instantiate an abstract class!" if @constructor is Predator
8+
9+
attack: ->
10+
throw new Error "You cannot call an abstract method!"
11+
12+
# ==============================
13+
# ABSTRACT OBSERVABLE
14+
# ==============================
15+
16+
class Prey
17+
constructor: ->
18+
throw new Error "You cannot instantiate an abstract class!" if @constructor is Prey
19+
@_predators = []
20+
21+
addPredator: (predator) ->
22+
@_predators.push predator
23+
24+
notifyPredators: ->
25+
situation = ""
26+
situation += predator.attack() for predator in @_predators
27+
situation
28+
29+
# ==============================
30+
# CONCRETE OBSERVERS
31+
# ==============================
32+
33+
class Lion extends Predator
34+
attack: ->
35+
"Lion attack!\n"
36+
37+
class Crocodile extends Predator
38+
attack: ->
39+
"Crocodile attack!\n"
40+
41+
# ==============================
42+
# CONCRETE OBSERVABLES
43+
# ==============================
44+
45+
class Gazelle extends Prey
46+
constructor: ->
47+
super
48+
49+
# ==============================
50+
# CLIENT CODE
51+
# ==============================
52+
53+
lion = new Lion
54+
crocodile = new Crocodile
55+
gazelle = new Gazelle
56+
57+
gazelle.addPredator lion
58+
gazelle.addPredator crocodile
59+
60+
console.log gazelle.notifyPredators()
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// ==============================
2+
// ABSTRACT OBSERVER
3+
// ==============================
4+
5+
interface Predator {
6+
attack(): string;
7+
}
8+
9+
// ==============================
10+
// ABSTRACT OBSERVABLE
11+
// ==============================
12+
13+
abstract class Prey {
14+
protected predators: Predator[] = [];
15+
16+
public addPredator(predator: Predator): void {
17+
this.predators.push(predator);
18+
}
19+
20+
public notifyPredators(): string {
21+
let situation: string = "";
22+
for (let predator of this.predators) {
23+
situation += predator.attack();
24+
}
25+
return situation;
26+
}
27+
}
28+
29+
// ==============================
30+
// CONCRETE OBSERVERS
31+
// ==============================
32+
33+
class Lion implements Predator {
34+
public attack(): string {
35+
return "Lion attack!\n";
36+
}
37+
}
38+
39+
class Crocodile implements Predator {
40+
public attack(): string {
41+
return "Crocodile attack!\n";
42+
}
43+
}
44+
45+
// ==============================
46+
// CONCRETE OBSERVABLES
47+
// ==============================
48+
49+
class Gazelle extends Prey {
50+
constructor() {
51+
super();
52+
}
53+
}
54+
55+
// ==============================
56+
// CLIENT CODE
57+
// ==============================
58+
59+
let lion: Predator = new Lion(),
60+
crocodile: Predator = new Crocodile(),
61+
gazelle: Prey = new Gazelle();
62+
63+
gazelle.addPredator(lion);
64+
gazelle.addPredator(crocodile);
65+
66+
console.log(gazelle.notifyPredators());
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
'use strict';
2+
3+
// ==============================
4+
// ABSTRACT OBSERVER
5+
// ==============================
6+
7+
var Predator = (function() {
8+
function Predator() {
9+
if (this.constructor === Predator) {
10+
throw new Error("You cannot instantiate an abstract class!");
11+
}
12+
}
13+
14+
Predator.prototype.attack = function () {
15+
throw new Error("You cannot call an abstract method!");
16+
};
17+
18+
return Predator;
19+
})();
20+
21+
// ==============================
22+
// ABSTRACT OBSERVABLE
23+
// ==============================
24+
25+
var Prey = (function () {
26+
function Prey() {
27+
if (this.constructor === Prey) {
28+
throw new Error("You cannot instantiate an abstract class!");
29+
}
30+
this._predators = [];
31+
}
32+
33+
Prey.prototype.addPredator = function (predator) {
34+
this._predators.push(predator);
35+
};
36+
37+
Prey.prototype.notifyPredators = function () {
38+
var situation = "";
39+
for (var i = 0, len = this._predators.length; i < len; i++) {
40+
situation += this._predators[i].attack();
41+
}
42+
return situation;
43+
};
44+
45+
return Prey;
46+
})();
47+
48+
// ==============================
49+
// CONCRETE OBSERVERS
50+
// ==============================
51+
52+
var Lion = (function () {
53+
function Lion() {}
54+
Lion.prototype = Object.create(Predator.prototype);
55+
Lion.prototype.constructor = Lion;
56+
57+
Lion.prototype.attack = function () {
58+
return "Lion attack!\n";
59+
};
60+
61+
return Lion;
62+
})();
63+
64+
var Crocodile = (function () {
65+
function Crocodile() {}
66+
Crocodile.prototype = Object.create(Predator.prototype);
67+
Crocodile.prototype.constructor = Crocodile;
68+
69+
Crocodile.prototype.attack = function () {
70+
return "Crocodile attack!\n";
71+
};
72+
73+
return Crocodile;
74+
})();
75+
76+
// ==============================
77+
// CONCRETE OBSERVABLES
78+
// ==============================
79+
80+
var Gazelle = (function () {
81+
function Gazelle() {
82+
Prey.call(this);
83+
}
84+
Gazelle.prototype = Object.create(Prey.prototype);
85+
Gazelle.prototype.constructor = Gazelle;
86+
87+
return Gazelle;
88+
})();
89+
90+
// ==============================
91+
// CLIENT CODE
92+
// ==============================
93+
94+
var lion = new Lion(),
95+
crocodile = new Crocodile(),
96+
gazelle = new Gazelle();
97+
98+
gazelle.addPredator(lion);
99+
gazelle.addPredator(crocodile);
100+
101+
console.log(gazelle.notifyPredators());
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// ==============================
2+
// ABSTRACT OBSERVER
3+
// ==============================
4+
5+
class Predator {
6+
constructor() {
7+
if (new.target !== undefined) {
8+
throw new Error("You cannot instantiate an abstract class!");
9+
}
10+
}
11+
12+
attack() {
13+
throw new Error("You cannot call an abstract method!");
14+
}
15+
}
16+
17+
// ==============================
18+
// ABSTRACT OBSERVABLE
19+
// ==============================
20+
21+
class Prey {
22+
constructor() {
23+
if (new.target !== undefined) {
24+
throw new Error("You cannot instantiate an abstract class!");
25+
}
26+
this._predators = [];
27+
}
28+
29+
addPredator(predator) {
30+
this._predators.push(predator);
31+
}
32+
33+
notifyPredators() {
34+
let situation = "";
35+
for (let predator of this._predators) {
36+
situation += predator.attack();
37+
}
38+
return situation;
39+
}
40+
}
41+
42+
// ==============================
43+
// CONCRETE OBSERVERS
44+
// ==============================
45+
46+
class Lion extends Predator {
47+
attack() {
48+
return "Lion attack!\n";
49+
}
50+
}
51+
52+
class Crocodile extends Predator {
53+
attack() {
54+
return "Crocodile attack!\n";
55+
}
56+
}
57+
58+
// ==============================
59+
// CONCRETE OBSERVABLES
60+
// ==============================
61+
62+
class Gazelle extends Prey {
63+
constructor() {
64+
super();
65+
}
66+
}
67+
68+
// ==============================
69+
// CLIENT CODE
70+
// ==============================
71+
72+
let lion = new Lion(),
73+
crocodile = new Crocodile(),
74+
gazelle = new Gazelle();
75+
76+
gazelle.addPredator(lion);
77+
gazelle.addPredator(crocodile);
78+
79+
console.log(gazelle.notifyPredators());

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /