Last active
February 7, 2023 20:40
-
-
Save gemmadlou/ca08fef90c0dfd68acfd to your computer and use it in GitHub Desktop.
Chain of Responsibility Pattern With Typescript - Adding Conditionals Together
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Example 01 | |
Business Says | |
------------- | |
We only want scores of 4 and above | |
Developer Says | |
-------------- | |
Simples. So we use an if statement. | |
*/ | |
var scores = [ | |
{ organiser: 's1', participant: 'p1', score: 3 }, | |
{ organiser: 's1', participant: 'p2', score: 6 }, | |
{ organiser: 's1', participant: 'p3', score: 4 }, | |
{ organiser: 's2', participant: 'p1', score: 4 }, | |
{ organiser: 's2', participant: 'p2', score: 0 }, | |
{ organiser: 's2', participant: 'p3', score: 1 } | |
] | |
var acceptedScores = []; | |
for (var n = 0; n < scores.length; n++) { | |
if (scores[n].score >= 4) { | |
acceptedScores.push(scores[n]); | |
} | |
} | |
for (var i in acceptedScores) { | |
document.write(acceptedScores[i].organiser + ' - ' + | |
acceptedScores[i].participant + ' - ' + | |
acceptedScores[i].score + '<br>'); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Example 02 | |
Business Says | |
------------- | |
We want scores of 4 and above only | |
And also scores that are a multiple of 3 | |
Developer Says | |
-------------- | |
Simples. So we use an if statement again. Just add the | |
new condition. | |
*/ | |
var scores = [ | |
{ organiser: 's1', participant: 'p1', score: 3 }, | |
{ organiser: 's1', participant: 'p2', score: 6 }, | |
{ organiser: 's1', participant: 'p3', score: 4 }, | |
{ organiser: 's2', participant: 'p1', score: 4 }, | |
{ organiser: 's2', participant: 'p2', score: 0 }, | |
{ organiser: 's2', participant: 'p3', score: 1 } | |
] | |
var acceptedScores = []; | |
for (var n = 0; n < scores.length; n++) { | |
if (scores[n].score >= 4 | |
&& scores[n].score % 3 === 0) { | |
acceptedScores.push(scores[n]); | |
} | |
} | |
for (var i in acceptedScores) { | |
document.write(acceptedScores[i].organiser + ' - ' + | |
acceptedScores[i].participant + ' - ' + | |
acceptedScores[i].score + '<br>'); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Example 03 | |
* | |
* Business Says | |
* ------------- | |
* We may have more requirements in future. | |
* And we want to mix and match requirements too. | |
* From the User Interface please. | |
* | |
* Developer Says | |
* --------------- | |
* Instead of hard-coding the if statement, we can use | |
* the chain of responsibility pattern to dynamically add | |
* conditions at run time. | |
* | |
* We can also add more business requirements later by | |
* creating a new class to handle the condition. | |
* | |
* Extra Note | |
* ---------- | |
* This example doesn't handle the array in any way special, but | |
* you would probably manipulate this array, or return something else | |
* completely. | |
*/ | |
/** | |
* Typescript allows us to create interfaces | |
*/ | |
interface ScoreInterface { | |
organiser: string; | |
participant: string; | |
score: number; | |
} | |
/** | |
* Which we can use to ensure we have the | |
* correct properties for our Score class | |
*/ | |
class Score implements ScoreInterface { | |
organiser: string; | |
participant: string; | |
score: number; | |
constructor(organiser: string, participant: string, score: number) { | |
this.organiser = organiser; | |
this.participant = participant; | |
this.score = score; | |
} | |
} | |
/** | |
* The handler interface requires 3 things | |
* 1. a handle method. You can pass it anything you want - but | |
* whatever you pass it has to go through every other handler. | |
* In this example, I'm using scores. | |
* | |
* 2. a handler property. This references the next handler class | |
* in the chain of handlers. | |
* | |
* 3. a addHandler method. This allows you to add handlers separate from | |
* class instantiation. | |
*/ | |
interface HandlerInterface { | |
handler: HandlerInterface; | |
handle(scores: ScoreInterface[]); | |
addHandler(handler: HandlerInterface); | |
} | |
class AboveScoreHandler implements HandlerInterface { | |
minimumscore: number; | |
handler: HandlerInterface; | |
constructor(minimumscore?: number) { | |
this.minimumscore = (typeof minimumscore === 'undefined') ? 0 : minimumscore; | |
} | |
handle(scores: ScoreInterface[]) { | |
if (scores[0].score < this.minimumscore) { | |
return false; | |
} else { | |
if (typeof this.handler !== 'undefined') { | |
return this.handler.handle(scores); | |
} else { | |
return true; | |
} | |
} | |
} | |
addHandler(handler: HandlerInterface) { | |
this.handler = handler; | |
} | |
} | |
var scores = [ | |
new Score('s1', 'p1', 3), | |
new Score('s1', 'p2', 6), | |
new Score('s1', 'p3', 4), | |
new Score('s2', 'p1', 4), | |
new Score('s2', 'p2', 0), | |
new Score('s2', 'p3', 1) | |
] | |
var acceptedScores: ScoreInterface[] = []; | |
while (scores.length > 0) { | |
var handler = new AboveScoreHandler(4); | |
if (handler.handle(scores)) { | |
acceptedScores.push(scores[0]); | |
} | |
scores.splice(0, 1); | |
} | |
for (var i in acceptedScores) { | |
document.write(acceptedScores[i].organiser + ' - ' + | |
acceptedScores[i].participant + ' - ' + | |
acceptedScores[i].score + '<br>'); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Example Final | |
* | |
* Now we can create new handler classes, and chain them | |
* together to get the same results. | |
*/ | |
interface ScoreInterface { | |
organiser: string; | |
participant: string; | |
score: number; | |
} | |
class Score implements ScoreInterface { | |
organiser: string; | |
participant: string; | |
score: number; | |
constructor(organiser: string, participant: string, score: number) { | |
this.organiser = organiser; | |
this.participant = participant; | |
this.score = score; | |
} | |
} | |
interface HandlerInterface { | |
handler: HandlerInterface; | |
handle(scores: ScoreInterface[]); | |
addHandler(handler: HandlerInterface); | |
} | |
class HandlerAbstractClass implements HandlerInterface { | |
handler: HandlerInterface; | |
handle(scores: ScoreInterface[]) { | |
if (typeof this.handler !== 'undefined') { | |
return this.handler.handle(scores); | |
} else { | |
return false; | |
} | |
} | |
addHandler(handler: HandlerInterface) { | |
this.handler = handler; | |
} | |
} | |
class AboveScoreHandler extends HandlerAbstractClass implements HandlerInterface { | |
minimumscore: number; | |
handler: HandlerInterface; | |
constructor(minimumscore?: number) { | |
super(); | |
this.minimumscore = (typeof minimumscore === 'undefined') ? 0 : minimumscore; | |
} | |
handle(scores: ScoreInterface[]) { | |
if (scores[0].score < this.minimumscore) { | |
return false; | |
} else { | |
if (typeof this.handler !== 'undefined') { | |
return this.handler.handle(scores); | |
} else { | |
return true; | |
} | |
} | |
} | |
} | |
class MultiplesOfHandler extends HandlerAbstractClass implements HandlerInterface { | |
multiples: number; | |
handler: HandlerInterface; | |
constructor(multiples?: number) { | |
super(); | |
this.multiples = (typeof multiples === 'undefined') ? 1 : multiples; | |
} | |
handle(scores: ScoreInterface[]) { | |
if (scores[0].score % this.multiples !== 0) { | |
return false; | |
} else { | |
if (typeof this.handler !== 'undefined') { | |
return this.handler.handle(scores); | |
} else { | |
return true; | |
} | |
} | |
} | |
} | |
var scores = [ | |
new Score('s1', 'p1', 3), | |
new Score('s1', 'p2', 6), | |
new Score('s1', 'p3', 4), | |
new Score('s2', 'p1', 4), | |
new Score('s2', 'p2', 0), | |
new Score('s2', 'p3', 1) | |
] | |
var acceptedScores: ScoreInterface[] = []; | |
while (scores.length > 0) { | |
/** Wiring up our handlers */ | |
var handler = new AboveScoreHandler(4); | |
var handler2 = new MultiplesOfHandler(3); | |
handler.addHandler(handler2); | |
if (handler.handle(scores)) { | |
acceptedScores.push(scores[0]); | |
} | |
scores.splice(0, 1); | |
} | |
for (var i in acceptedScores) { | |
document.write(acceptedScores[i].organiser + ' - ' + | |
acceptedScores[i].participant + ' - ' + | |
acceptedScores[i].score + '<br>'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment