Skip to content Skip to sidebar Skip to footer

Is This Following The Strategy Design Pattern

Me and my colleague have a disagreement about if this follows the strategy pattern or not. We have a react component List which expects a 'strategy' prop that has the following sha

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"