Is This Following The Strategy Design Pattern
Solution 1:
The constructors for the strategies don't have any relevance for whether something is or isn't a strategy. The goal of the strategy pattern is to extract an operation to be independant from the class and to allow you to determine how a class behaves, without altering it.
Consider the following, we want to make a trivial "calculator" that takes two values and operates with them. It then displays that result in some way. We want to extract the logic for:
- the calculation - how two numbers are handled
- the display - how the result is shown
This would mean that we can change how the calculator works without altering the class itself. So, we extract two strategies:
interfaceCalculationStrategy {
doMaths: (a: number, b: number) =>number
}
interfaceDisplayStrategy {
show: (num: number) =>void
}
And we could supply multiple implementations:
//calculation strategiesclassAddStrategy {
doMaths(a, b) {
return a + b;
}
}
classMultiplyByConstantStrategy {
constructor(x) {
this.x = x;
}
doMaths(a, b) {
return (a + b) * this.x;
}
}
//display strategiesclassConsoleDisplayStrategy {
show(num) {
console.log(num.toFixed(2))
}
}
classHTMLDisplayStrategy {
constructor(elementSelector) {
this.inputElement = document.querySelector(elementSelector);
}
show(num) {
this.inputElement.value = num;
}
}
//calculate classclassCalculate {
constructor(operationHandler, displayHandler) {
this.operationHandler = operationHandler;
this.displayHandler = displayHandler;
}
calculate(a, b) {
const result = this.operationHandler.doMaths(a, b);
this.displayHandler.show(result);
}
}
/* usage *///calculate the total for a bill + tipconst tip = newCalculate(
newMultiplyByConstantStrategy(1.15),
newHTMLDisplayStrategy("#totalWithTip")
);
document.querySelector("#billTotal")
.addEventListener("click", () => {
const coffee = Number(document.querySelector("#coffeePrice").value);
const bagel = Number(document.querySelector("#bagelPrice").value);
tip.calculate(coffee, bagel);
});
//just display a calculation on the pageconst showAdd = newCalculate(
newAddStrategy(),
newHTMLDisplayStrategy("#addResult")
);
showAdd.calculate(2, 8);
//print a sumconst printAdd = newCalculate(
newAddStrategy(),
newConsoleDisplayStrategy()
);
document.querySelector("#printSum")
.addEventListener("click", () => {
const a = Number(document.querySelector("#a").value);
const b = Number(document.querySelector("#b").value);
printAdd.calculate(a, b);
});
.as-console-wrapper {
/* prevent the console output from covering the page */position: initial !important;
}
<pre>MultiplyByConstantStrategy + HTMLDisplayStrategy</pre><div><labelfor="coffeePrice">Price for coffee:</label><inputid="coffeePrice"value="2"type="number" /></div><div><labelfor="bagelPrice">Price for bagel:</label><inputid="bagelPrice"value="8"type="number" /></div><div><labelfor="totalWithTip">You owe:</label><inputid="totalWithTip"readonly/></div><buttonid="billTotal">Bill please!</button><hr/><pre>AddStrategy + HTMLDisplayStrategy</pre><div><labelfor="addResult">2 + 8 = </label><inputid="addResult"readonly/></div><hr/><pre>AddStrategy + ConsoleDisplayStrategy</pre><div><inputid="a"value="2"type="number" />
+
<inputid="b"value="8"type="number" /></div><buttonid="printSum">print the sum</button>
The goal is reached here. We've successfully decoupled the calculation and display. We can alter each one without having to change the other or the Calculate
class. And this is what the strategy pattern tries to solve. The fact that the strategies are constructed with different parameters is irrelevant for this outcome.
Post a Comment for "Is This Following The Strategy Design Pattern"