Strategy Design Pattern
Structural: Strategy Pattern
What is the Strategy Design Pattern in JavaScript?
View Answer:
This pattern's objects are as follows:
Context -- example code: Shipping
- keeps track of the current Strategy object
- provides an interface by which clients can request Strategy computations
- enables clients to adjust their strategy
Strategy -- example code: UPS, USPS, FedEx
- implements the algorithm using the Strategy interface
Here's an example using modern JavaScript where different shipping strategies are implemented for an ecommerce system:
class Shipping {
constructor() {
this.company = '';
}
setStrategy(company) {
this.company = company;
}
calculate(package) {
return this.company.calculate(package);
}
}
class UPS {
calculate(package) {
// calculations...
return '$45.95';
}
}
class USPS {
calculate(package) {
// calculations...
return '$39.40';
}
}
class Fedex {
calculate(package) {
// calculations...
return '$43.20';
}
}
// usage
const package = { from: '76712', to: '10012', weigth: 'lkg' };
// the Shipping object uses the strategy interface
const shipping = new Shipping();
shipping.setStrategy(new UPS());
console.log(`UPS Strategy: ${shipping.calculate(package)}`);
// Output: UPS Strategy: $45.95
shipping.setStrategy(new USPS());
console.log(`USPS Strategy: ${shipping.calculate(package)}`);
// Output: USPS Strategy: $39.40
shipping.setStrategy(new Fedex());
console.log(`Fedex Strategy: ${shipping.calculate(package)}`);
// Output: Fedex Strategy: $43.20
In this example, Shipping
is the context, UPS
, USPS
, and Fedex
are strategy classes, and calculate
is the method the context will use to interchange strategies. This pattern provides a way to encapsulate related algorithms to make them interchangeable and provides the flexibility to select the most appropriate strategy for a particular scenario.
The Strategy pattern belongs to which pattern group?
View Answer:
When should the JavaScript Strategy Pattern be used?
View Answer:
Strategy Pattern Use-Cases:
- When you need to employ several algorithms with varying versions, you must construct a concrete class (this may include one or more functions) to implement your algorithm.
- When there are conditional statements around by several connected algorithms
- When the majority of your objects or classes exhibit similar behaviors
What are some of the advantages of employing the Strategy pattern?
View Answer:
- At runtime, you can alter the algorithms utilized within an object.
- You can separate an algorithm's implementation specifics from the code that utilizes it.
- It use the composition in place of inheritance
- The principle of open/closed. You may implement new tactics without changing the context.
What's a disadvantage of the Strategy Pattern?
View Answer:
Drawbacks of the Strategy Pattern:
- If you only have a few algorithms that seldom change, there's no point in complicating the program with new classes and interfaces that come with the pattern.
- Clients must understand the distinctions between tactics to choose the best one.
- Many current programming languages feature functional types, which allow you to implement different variants of an algorithm within a collection of anonymous functions. You may then utilize these methods the same way you used Strategy objects, but without cluttering your code with unnecessary classes and interfaces.
Are there any alternatives to using the Strategy pattern?
View Answer:
- If you only have a few algorithms that seldom change, there's no point in complicating the program with new classes and interfaces that come with the pattern.
- Clients must understand the distinctions between tactics to choose the best one.
- Many current programming languages feature functional types, which allow you to implement different variants of an algorithm within a collection of anonymous functions. You may then utilize these methods the same way you used Strategy objects, but without cluttering your code with unnecessary classes and interfaces.
What are the main components of the Strategy Pattern?
View Answer:
Here's an example with a Sorter
context and different sorting strategies.
// Context
class Sorter {
constructor(sortStrategy) {
this.sortStrategy = sortStrategy;
}
setStrategy(sortStrategy) {
this.sortStrategy = sortStrategy;
}
sort(dataset) {
return this.sortStrategy.sort(dataset);
}
}
// Strategy
class SortStrategy {
sort(dataset) {
throw new Error("This method must be overridden in a derived class.");
}
}
// Concrete Strategy A
class BubbleSortStrategy extends SortStrategy {
sort(dataset) {
console.log("Sorting using bubble sort");
// Perform bubble sort and return sorted dataset
return dataset.sort((a, b) => a - b);
}
}
// Concrete Strategy B
class QuickSortStrategy extends SortStrategy {
sort(dataset) {
console.log("Sorting using quick sort");
// Perform quick sort and return sorted dataset
return dataset.sort((a, b) => a - b); // Simplified for example purposes
}
}
// Usage
const dataset = [1, 5, 4, 3, 2, 8];
let sorter = new Sorter(new BubbleSortStrategy());
sorter.sort(dataset); // Outputs: Sorting using bubble sort
sorter.setStrategy(new QuickSortStrategy());
sorter.sort(dataset); // Outputs: Sorting using quick sort
In this example, Sorter
is the Context, SortStrategy
is the Strategy, and BubbleSortStrategy
and QuickSortStrategy
are Concrete Strategies. The Sorter
can use different sorting strategies interchangeably depending on the needs of the application.