Skip to content

Commit c0bcc51

Browse files
author
Badacadabra
committed
Add Composite (ES5 + ES6 + CoffeeScript)
1 parent c8b07d2 commit c0bcc51

File tree

6 files changed

+245
-0
lines changed

6 files changed

+245
-0
lines changed
2 KB
Binary file not shown.
12.3 KB
Loading
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Synopsis
2+
3+
My little brother's room is generally a big mess, but recently my mother bought him some funny toy boxes of different sizes (like a 3D puzzle) so he can put his toys in it.
4+
5+
# Problem
6+
7+
Here a toy box is, to some extent, a toy in itself that can contain other toys. These toys can be simple ones like, for instance, balls. But they can be complex ones too, like smaller toy boxes which also may contain other balls and/or even smaller toy boxes, etc. This situation is not easy to describe through code...
8+
9+
# Solution
10+
11+
A good idea is to consider a group of toys like a simple toy. So a toy box full of toys is just a toy after all!
12+
13+
The Composite design pattern is useful in this kind of situation. To implement this one, we need:
14+
15+
* An abstract representation of a toy (abstract class or interface)
16+
* Concrete toys, especially a simple one (ball) and a complex one (toy box)
17+
* Methods for the complex toy to manage (simple and complex) toys inside of it
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"use strict"
2+
3+
# ==============================
4+
# ABSTRACT COMPONENT
5+
# ==============================
6+
7+
class Toy
8+
constructor: ->
9+
throw new Error "You cannot instantiate an abstract class!" if @constructor is Toy
10+
11+
description: ->
12+
throw new Error "You cannot call an abstract method!"
13+
14+
# ==============================
15+
# SIMPLE (CONCRETE) COMPONENT
16+
# ==============================
17+
18+
# A ball does not contain anything
19+
class Ball extends Toy
20+
description: ->
21+
"There's a ball!\n"
22+
23+
# ==============================
24+
# COMPOSITE (CONCRETE) COMPONENT
25+
# ==============================
26+
27+
# A toy box is a toy entity which contains toys, including smaller toy boxes
28+
class ToyBox extends Toy
29+
constructor: ->
30+
@_toys = []
31+
32+
description: ->
33+
"There's a toy box!\n"
34+
35+
add: (toy) ->
36+
@_toys.push(toy)
37+
38+
inventory: ->
39+
inventory = "Let's open the toy box...\n"
40+
for toy in @_toys
41+
inventory += toy.description()
42+
if toy instanceof ToyBox
43+
inventory += toy.inventory()
44+
inventory
45+
46+
# ==============================
47+
# CLIENT CODE
48+
# ==============================
49+
50+
# Here we organize our toys in an optimal way
51+
ball1 = new Ball
52+
ball2 = new Ball
53+
ball3 = new Ball
54+
bigToyBox = new ToyBox
55+
smallToyBox = new ToyBox
56+
57+
smallToyBox.add ball1
58+
bigToyBox.add ball2
59+
bigToyBox.add ball3
60+
bigToyBox.add smallToyBox
61+
62+
# Now we open our big toy box...
63+
console.log bigToyBox.inventory()
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
'use strict';
2+
3+
// ==============================
4+
// ABSTRACT COMPONENT
5+
// ==============================
6+
7+
var Toy = (function () {
8+
function Toy() {
9+
if (this.constructor === Toy) {
10+
throw new Error("You cannot instantiate an abstract class!");
11+
}
12+
}
13+
14+
Toy.prototype.description = function () {
15+
throw new Error("You cannot call an abstract method!");
16+
};
17+
18+
return Toy;
19+
})();
20+
21+
// ==============================
22+
// SIMPLE (CONCRETE) COMPONENT
23+
// ==============================
24+
25+
// A ball does not contain anything
26+
var Ball = (function () {
27+
function Ball() {}
28+
Ball.prototype = Object.create(Toy.prototype);
29+
Ball.prototype.constructor = Ball;
30+
31+
Ball.prototype.description = function () {
32+
return "There's a ball!\n";
33+
};
34+
35+
return Ball;
36+
})();
37+
38+
// ==============================
39+
// COMPOSITE (CONCRETE) COMPONENT
40+
// ==============================
41+
42+
// A toy box is a toy entity which contains toys, including smaller toy boxes
43+
var ToyBox = (function () {
44+
function ToyBox() {
45+
this.toys = [];
46+
}
47+
ToyBox.prototype = Object.create(Toy.prototype);
48+
ToyBox.prototype.constructor = ToyBox;
49+
50+
ToyBox.prototype.description = function () {
51+
return "There's a toy box!\n";
52+
};
53+
54+
ToyBox.prototype.add = function (toy) {
55+
this.toys.push(toy);
56+
};
57+
58+
ToyBox.prototype.inventory = function () {
59+
var inventory = "Let's open the toy box...\n";
60+
for (var i = 0; i < this.toys.length; i++) {
61+
inventory += this.toys[i].description();
62+
if (this.toys[i] instanceof ToyBox) {
63+
inventory += this.toys[i].inventory();
64+
}
65+
}
66+
return inventory;
67+
};
68+
69+
return ToyBox;
70+
})();
71+
72+
// ==============================
73+
// CLIENT CODE
74+
// ==============================
75+
76+
// Here we organize our toys in an optimal way
77+
var ball1 = new Ball(),
78+
ball2 = new Ball(),
79+
ball3 = new Ball(),
80+
bigToyBox = new ToyBox(),
81+
smallToyBox = new ToyBox();
82+
83+
smallToyBox.add(ball1);
84+
bigToyBox.add(ball2);
85+
bigToyBox.add(ball3);
86+
bigToyBox.add(smallToyBox);
87+
88+
// Now we open our big toy box...
89+
console.log(bigToyBox.inventory());
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// ==============================
2+
// ABSTRACT COMPONENT
3+
// ==============================
4+
5+
class Toy {
6+
constructor() {
7+
if (new.target !== undefined) {
8+
throw new Error("You cannot instantiate an abstract class!");
9+
}
10+
}
11+
12+
description() {
13+
throw new Error("You cannot call an abstract method!");
14+
}
15+
}
16+
17+
// ==============================
18+
// SIMPLE (CONCRETE) COMPONENT
19+
// ==============================
20+
21+
// A ball does not contain anything
22+
class Ball extends Toy {
23+
description() {
24+
return "There's a ball!\n";
25+
}
26+
}
27+
28+
// ==============================
29+
// COMPOSITE (CONCRETE) COMPONENT
30+
// ==============================
31+
32+
// A toy box is a toy entity which contains toys, including smaller toy boxes.
33+
class ToyBox extends Toy {
34+
constructor() {
35+
super();
36+
this._toys = [];
37+
}
38+
39+
description() {
40+
return "There's a toy box!\n";
41+
}
42+
43+
add(toy) {
44+
this._toys.push(toy);
45+
}
46+
47+
inventory() {
48+
let inventory = "Let's open the toy box...\n";
49+
for (let toy of this._toys) {
50+
inventory += toy.description();
51+
if (toy instanceof ToyBox) {
52+
inventory += toy.inventory();
53+
}
54+
}
55+
return inventory;
56+
}
57+
}
58+
59+
// ==============================
60+
// CLIENT CODE
61+
// ==============================
62+
63+
// Here we organize our toys in an optimal way
64+
let ball1 = new Ball(),
65+
ball2 = new Ball(),
66+
ball3 = new Ball(),
67+
bigToyBox = new ToyBox(),
68+
smallToyBox = new ToyBox();
69+
70+
smallToyBox.add(ball1);
71+
smallToyBox.add(ball2);
72+
bigToyBox.add(ball3);
73+
bigToyBox.add(smallToyBox);
74+
75+
// Now we open our big toy box...
76+
console.log(bigToyBox.inventory());

0 commit comments

Comments
 (0)