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 4749af5

Browse files
author
Badacadabra
committed
Add Strategy (ES5 + ES6 + CoffeeScript + TypeScript)
1 parent e73f3aa commit 4749af5

File tree

7 files changed

+259
-0
lines changed

7 files changed

+259
-0
lines changed

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Synopsis
2+
3+
I am playing a fighting game and I do not know my opponent. Should I prefer an offensive or defensive style?
4+
5+
# Problem
6+
7+
Since the opponent is unknown, the player has to choose a fighting strategy on the fly.
8+
In programming terms, we can say that an algorithm has to be selected at runtime, among several available algorithms.
9+
10+
# Solution
11+
12+
The Strategy design pattern is exactly what we need in this kind of situation. To implement this pattern, we can have:
13+
14+
* A concrete context (FightingGame) which contains a reference to a strategy
15+
* An abstract representation of a strategy (abstract class or interface)
16+
* Concrete strategies (Offense & Defense)
2.12 KB
Binary file not shown.
16.2 KB
Loading[フレーム]
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# ==============================
2+
# CONCRETE CONTEXT
3+
# ==============================
4+
5+
class FightingGame
6+
constructor: ->
7+
@_strategy = null
8+
9+
play: ->
10+
@_strategy.fight()
11+
12+
setStrategy: (fightStyle) ->
13+
@_strategy = fightStyle
14+
15+
# ==============================
16+
# ABSTRACT STRATEGY
17+
# ==============================
18+
19+
class Strategy
20+
constructor: ->
21+
throw new Error "You cannot instantiate an abstract class!" if @constructor is Strategy
22+
23+
fight: ->
24+
throw new Error "You cannot call an abstract method!"
25+
26+
# ==============================
27+
# CONCRETE STRATEGIES
28+
# ==============================
29+
30+
class Offense extends Strategy
31+
fight: ->
32+
"Fight with an offensive style"
33+
34+
class Defense extends Strategy
35+
fight: ->
36+
"Fight with a defensive style"
37+
38+
# ==============================
39+
# CLIENT CODE
40+
# ==============================
41+
42+
game = new FightingGame
43+
offense = new Offense
44+
defense = new Defense
45+
46+
game.setStrategy defense
47+
console.log "ROUND 1 - #{game.play()}"
48+
game.setStrategy offense
49+
console.log "ROUND 2 - #{game.play()}"
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// ==============================
2+
// CONCRETE CONTEXT
3+
// ==============================
4+
5+
class FightingGame {
6+
private strategy: Strategy;
7+
8+
play(): string {
9+
return this.strategy.fight();
10+
}
11+
12+
setStrategy(fightStyle: Strategy): void {
13+
this.strategy = fightStyle;
14+
}
15+
}
16+
17+
// ==============================
18+
// ABSTRACT STRATEGY
19+
// ==============================
20+
21+
interface Strategy {
22+
fight(): string;
23+
}
24+
25+
// ==============================
26+
// CONCRETE STRATEGIES
27+
// ==============================
28+
29+
class Offense implements Strategy {
30+
fight(): string {
31+
return "Fight with an offensive style";
32+
}
33+
}
34+
35+
class Defense implements Strategy {
36+
fight(): string {
37+
return "Fight with a defensive style";
38+
}
39+
}
40+
41+
// ==============================
42+
// CLIENT CODE
43+
// ==============================
44+
45+
let game: FightingGame = new FightingGame(),
46+
offense: Strategy = new Offense(),
47+
defense: Strategy = new Defense();
48+
49+
game.setStrategy(defense);
50+
console.log(`ROUND 1 - ${game.play()}`);
51+
game.setStrategy(offense);
52+
console.log(`ROUND 2 - ${game.play()}`);
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
'use strict';
2+
3+
// ==============================
4+
// CONCRETE CONTEXT
5+
// ==============================
6+
7+
var FightingGame = (function () {
8+
var strategy = null;
9+
10+
function FightingGame() {}
11+
12+
FightingGame.prototype.play = function () {
13+
return strategy.fight();
14+
};
15+
16+
FightingGame.prototype.setStrategy = function (fightStyle) {
17+
strategy = fightStyle;
18+
};
19+
20+
return FightingGame;
21+
})();
22+
23+
// ==============================
24+
// ABSTRACT STRATEGY
25+
// ==============================
26+
27+
var Strategy = (function() {
28+
function Strategy() {
29+
if (this.constructor === Strategy) {
30+
throw new Error("You cannot instantiate an abstract class!");
31+
}
32+
}
33+
34+
Strategy.prototype.fight = function () {
35+
throw new Error("You cannot call an abstract method!");
36+
};
37+
38+
return Strategy;
39+
})();
40+
41+
// ==============================
42+
// CONCRETE STRATEGIES
43+
// ==============================
44+
45+
var Offense = (function () {
46+
function Offense() {}
47+
Offense.prototype = Object.create(Strategy.prototype);
48+
Offense.prototype.constructor = Offense;
49+
50+
Offense.prototype.fight = function () {
51+
return "Fight with an offensive style";
52+
};
53+
54+
return Offense;
55+
})();
56+
57+
var Defense = (function () {
58+
function Defense() {}
59+
Defense.prototype = Object.create(Strategy.prototype);
60+
Defense.prototype.constructor = Defense;
61+
62+
Defense.prototype.fight = function () {
63+
return "Fight with a defensive style";
64+
};
65+
66+
return Defense;
67+
})();
68+
69+
// ==============================
70+
// CLIENT CODE
71+
// ==============================
72+
73+
var game = new FightingGame(),
74+
offense = new Offense(),
75+
defense = new Defense();
76+
77+
game.setStrategy(defense);
78+
console.log("ROUND 1 - " + game.play());
79+
game.setStrategy(offense);
80+
console.log("ROUND 2 - " + game.play());
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// ==============================
2+
// CONCRETE CONTEXT
3+
// ==============================
4+
5+
class FightingGame {
6+
constructor() {
7+
this._strategy = null;
8+
}
9+
10+
play() {
11+
return this._strategy.fight();
12+
}
13+
14+
setStrategy(fightStyle) {
15+
this._strategy = fightStyle;
16+
}
17+
}
18+
19+
// ==============================
20+
// ABSTRACT STRATEGY
21+
// ==============================
22+
23+
class Strategy {
24+
constructor() {
25+
if (new.target !== undefined) {
26+
throw new Error("You cannot instantiate an abstract class!");
27+
}
28+
}
29+
30+
fight() {
31+
throw new Error("You cannot call an abstract method!");
32+
}
33+
}
34+
35+
// ==============================
36+
// CONCRETE STRATEGIES
37+
// ==============================
38+
39+
class Offense extends Strategy {
40+
fight() {
41+
return "Fight with an offensive style";
42+
}
43+
}
44+
45+
class Defense extends Strategy {
46+
fight() {
47+
return "Fight with a defensive style";
48+
}
49+
}
50+
51+
// ==============================
52+
// CLIENT CODE
53+
// ==============================
54+
55+
let game = new FightingGame(),
56+
offense = new Offense(),
57+
defense = new Defense();
58+
59+
game.setStrategy(defense);
60+
console.log(`ROUND 1 - ${game.play()}`);
61+
game.setStrategy(offense);
62+
console.log(`ROUND 2 - ${game.play()}`);

0 commit comments

Comments
(0)

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