Skip to content

Commit ccdf660

Browse files
author
Joao Paulo Monteiro
committed
Add code of Decorator Pattern: The Long Night
1 parent 2267798 commit ccdf660

File tree

6 files changed

+220
-1
lines changed

6 files changed

+220
-1
lines changed

decorator/Character.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
class Character{
2+
constructor(name){
3+
this._name = name;
4+
this._life = 0;
5+
}
6+
7+
set life(life){
8+
this._life = (life > 0 ) ? life : 0;
9+
}
10+
11+
get life(){
12+
return this._life;
13+
}
14+
15+
get name(){
16+
return this._name;
17+
}
18+
19+
attack(){
20+
throw new Error('Este método precisa ser implementado nas subclasses');
21+
}
22+
23+
defend(){
24+
throw new Error('Este método precisa ser implementado nas subclasses');
25+
}
26+
27+
receiveHit(attack){
28+
throw new Error('Este método precisa ser implementado nas subclasses');
29+
}
30+
31+
isAlive(){
32+
throw new Error('Este método precisa ser implementado nas subclasses');
33+
}
34+
35+
toString(){
36+
throw new Error('Este método precisa ser implementado nas subclasses');
37+
}
38+
}
39+
40+
export default Character;

decorator/CharacterDecorator.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Character } from "./Character";
2+
3+
class CharacterDecorator{
4+
constructor(character){
5+
this._character = character;
6+
}
7+
8+
attack(){
9+
return this._character.attack();
10+
}
11+
12+
defend(){
13+
return this._character.defend();
14+
}
15+
16+
isAlive(){
17+
return this._character.isAlive();
18+
}
19+
20+
set life(life){
21+
this._character.life = life;
22+
}
23+
24+
get life(){
25+
return this._character.life;
26+
}
27+
28+
get name(){
29+
return this._character.name;
30+
}
31+
32+
receiveHit(hit){
33+
this._character.receiveHit(hit);
34+
}
35+
36+
37+
toString(){
38+
return `${this._character.name} - ${this._character.life}`;
39+
}
40+
}
41+
42+
export default CharacterDecorator;

decorator/SimpleCharacter.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import Character from './Character';
2+
3+
class SimpleCharacter extends Character{
4+
constructor(name){
5+
super(name);
6+
this._life = 100;
7+
}
8+
9+
attack(){
10+
return 1;
11+
}
12+
13+
defend(){
14+
return 1;
15+
}
16+
17+
receiveHit(hit){
18+
const damage = ( hit * Math.random() ) - ( this.defend() * Math.random() );
19+
if(damage > 0){
20+
this.life = this.life - damage;
21+
}
22+
}
23+
24+
isAlive(){
25+
return this.life > 0;
26+
}
27+
28+
toString(){
29+
return `Simple Character. Name: ${this.name}`;
30+
}
31+
}
32+
33+
export default SimpleCharacter;

decorator/WhiteWalkerDecorator.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import CharacterDecorator from './CharacterDecorator';
2+
3+
class WhiteWalkerDecorator extends CharacterDecorator{
4+
constructor(character){
5+
super(character);
6+
this._power = Math.random();
7+
}
8+
9+
set power(power){
10+
this._power = power;
11+
}
12+
13+
_whiteWalkerModifier(){
14+
return Math.random() * this._power;
15+
}
16+
17+
attack(){
18+
return this._whiteWalkerModifier() * super.attack();
19+
}
20+
21+
defend(){
22+
return this._whiteWalkerModifier() * super.defend();
23+
}
24+
25+
}
26+
27+
export default WhiteWalkerDecorator;

decorator/main.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import CharacterDecorator from './CharacterDecorator';
2+
import SimpleCharacter from './SimpleCharacter';
3+
import WhiteWalkerDecorator from './WhiteWalkerDecorator';
4+
5+
const NUM_HUMANS = 20;
6+
const humans = Array.from(
7+
Array(NUM_HUMANS),
8+
(_, index) => new CharacterDecorator(new SimpleCharacter(`Human${index}`))
9+
);
10+
11+
const nightKing = createNightKing();
12+
13+
const whiteWalkers = [nightKing];
14+
15+
console.log('The War started!');
16+
17+
let human;
18+
let whiteWalker;
19+
20+
while(!isWarFinished(humans, whiteWalkers)){
21+
human = humans.pop();
22+
whiteWalker = whiteWalkers.pop();
23+
24+
while(human.isAlive() && whiteWalker.isAlive()){
25+
whiteWalker.receiveHit(human.attack());
26+
human.receiveHit(whiteWalker.attack());
27+
}
28+
29+
if(human.isAlive()){
30+
console.log('Human Win!');
31+
log(human, whiteWalker);
32+
}
33+
34+
if(whiteWalker.isAlive()){
35+
console.log('WhiteWalker Win!...');
36+
whiteWalkers.push(whiteWalker);
37+
console.log('... Human now is a White Walker:', human.name);
38+
whiteWalkers.push(
39+
new WhiteWalkerDecorator(
40+
new SimpleCharacter(`White Walker: ${human.name}`)
41+
)
42+
);
43+
44+
console.log('----WhiteWalkers----');
45+
console.table(whiteWalkers);
46+
console.log('----Humans----');
47+
console.table(humans);
48+
49+
}
50+
}
51+
52+
console.log('The War is Finished');
53+
54+
if(humans.length > 0){
55+
console.log('The long night is over!');
56+
}else{
57+
console.log('The long night stands forever!');
58+
}
59+
60+
function isWarFinished(humans, whiteWalkers){
61+
return humans.length == 0 || whiteWalkers.length == 0;
62+
}
63+
64+
function log(human, whiteWalker){
65+
console.log('--------------------');
66+
console.log(`${human.toString()} Vs ${whiteWalker.toString()}`);
67+
console.log();
68+
console.log('--------------------');
69+
}
70+
71+
function createNightKing(){
72+
const nightKing = new WhiteWalkerDecorator(new SimpleCharacter('Night King'));
73+
nightKing.life = 500;
74+
nightKing.power = 2;
75+
return nightKing;
76+
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
},
66
"scripts": {
77
"strategy": "nodemon strategy/main.js",
8-
"observer": "nodemon observer/main.js"
8+
"observer": "nodemon observer/main.js",
9+
"decorator": "nodemon decorator/main.js"
910
},
1011
"name": "design_patterns",
1112
"version": "1.0.0",

0 commit comments

Comments
 (0)