The Strategy pattern helps you change how a program works by swapping different methods easily. It keeps your code clean and flexible.
Strategy pattern in PHP
<?php interface Strategy { public function execute(string $data): string; } class ConcreteStrategyA implements Strategy { public function execute(string $data): string { return strtoupper($data); } } class ConcreteStrategyB implements Strategy { public function execute(string $data): string { return strtolower($data); } } class Context { private Strategy $strategy; public function __construct(Strategy $strategy) { $this->strategy = $strategy; } public function setStrategy(Strategy $strategy): void { $this->strategy = $strategy; } public function doAction(string $data): string { return $this->strategy->execute($data); } }
The Strategy interface defines a method all strategies must implement.
The Context class uses a strategy object to perform its task.
<?php interface Strategy { public function execute(string $data): string; } class UpperCaseStrategy implements Strategy { public function execute(string $data): string { return strtoupper($data); } } class LowerCaseStrategy implements Strategy { public function execute(string $data): string { return strtolower($data); } } class Context { private Strategy $strategy; public function __construct(Strategy $strategy) { $this->strategy = $strategy; } public function doAction(string $data): string { return $this->strategy->execute($data); } } $context = new Context(new UpperCaseStrategy()); echo $context->doAction("Hello World");
<?php $context = new Context(new LowerCaseStrategy()); echo $context->doAction("Hello World");
This program shows how the context uses two different strategies to change the text. First, it makes the text uppercase, then lowercase.
<?php interface Strategy { public function execute(string $data): string; } class UpperCaseStrategy implements Strategy { public function execute(string $data): string { return strtoupper($data); } } class LowerCaseStrategy implements Strategy { public function execute(string $data): string { return strtolower($data); } } class Context { private Strategy $strategy; public function __construct(Strategy $strategy) { $this->strategy = $strategy; } public function setStrategy(Strategy $strategy): void { $this->strategy = $strategy; } public function doAction(string $data): string { return $this->strategy->execute($data); } } $context = new Context(new UpperCaseStrategy()); echo $context->doAction("Hello Strategy Pattern!") . "\n"; $context->setStrategy(new LowerCaseStrategy()); echo $context->doAction("Hello Strategy Pattern!") . "\n";
Each strategy class must follow the same interface so the context can use them interchangeably.
You can add new strategies without changing the context code.
Use the Strategy pattern to keep your code easy to read and maintain.
The Strategy pattern lets you swap different ways to do a task easily.
It helps avoid complex if-else statements by using separate classes.
The context class uses a strategy object to perform actions.
Practice
What is the main purpose of the Strategy pattern in PHP?
Solution
Step 1: Understand the Strategy pattern concept
The Strategy pattern is designed to let you swap different algorithms or behaviors easily without changing the main code that uses them.Step 2: Identify the correct purpose
Among the options, only To allow changing the algorithm or behavior at runtime without modifying the context. describes this behavior: changing the algorithm at runtime without modifying the context class.Final Answer:
To allow changing the algorithm or behavior at runtime without modifying the context. -> Option AQuick Check:
Strategy pattern = change behavior easily [OK]
- Confusing Strategy with Singleton or Factory patterns
- Thinking it manages data storage
- Assuming it handles errors
Which of the following is the correct way to define a strategy interface in PHP?
?Solution
Step 1: Recall PHP interface syntax
In PHP, interfaces are declared with the keywordinterface, and methods inside must be declared without a body and with visibility (usually public).Step 2: Check each option
interface Strategy { public function execute(); } correctly declares an interface with a public method without a body. class Strategy { function execute() {} } uses a class, not interface. interface Strategy { function execute() {} } incorrectly provides a method body inside interface. abstract class Strategy { public execute(); } uses abstract class but misses parentheses and visibility.Final Answer:
interface Strategy { public function execute(); } -> Option CQuick Check:
Interface method = declaration only [OK]
- Adding method body inside interface
- Using class instead of interface
- Omitting visibility keyword
What will be the output of the following PHP code using the Strategy pattern?
interface Strategy {
public function execute();
}
class AddStrategy implements Strategy {
public function execute() {
return 5 + 3;
}
}
class MultiplyStrategy implements Strategy {
public function execute() {
return 5 * 3;
}
}
class Context {
private Strategy $strategy;
public function __construct(Strategy $strategy) {
$this->strategy = $strategy;
}
public function executeStrategy() {
return $this->strategy->execute();
}
}
$context = new Context(new MultiplyStrategy());
echo $context->executeStrategy();
Solution
Step 1: Understand the code flow
The code defines two strategies: AddStrategy returns 5+3=8, MultiplyStrategy returns 5*3=15. The Context class uses the strategy passed in constructor.Step 2: Identify which strategy is used
The context is created withnew MultiplyStrategy(), so callingexecuteStrategy()returns 15.Final Answer:
15 -> Option BQuick Check:
MultiplyStrategy returns 15 [OK]
- Confusing AddStrategy and MultiplyStrategy output
- Thinking interface cannot be instantiated (only concrete classes)
- Ignoring which strategy is passed
Identify the error in the following PHP code implementing the Strategy pattern:
interface Strategy {
public function execute();
}
class ConcreteStrategy implements Strategy {
public function execute() {
echo "Running strategy";
}
}
class Context {
private $strategy;
public function __construct(Strategy $strategy) {
$this->strategy = $strategy;
}
public function executeStrategy() {
$this->strategy->execute;
}
}
$context = new Context(new ConcreteStrategy());
$context->executeStrategy();
Solution
Step 1: Check method call syntax in Context
InsideexecuteStrategy(), the code calls$this->strategy->execute;without parentheses, so the method is not actually called.Step 2: Identify correct fix
Method calls require parentheses even if no arguments:$this->strategy->execute();.Final Answer:
Missing parentheses when calling execute method -> Option DQuick Check:
Method call needs () [OK]
- Forgetting parentheses on method calls
- Confusing interface method declaration with implementation
- Ignoring type hints in constructor
You want to add a new strategy SubtractStrategy to the existing PHP Strategy pattern code. Which of the following is the best way to implement it?
interface Strategy {
public function execute(int $a, int $b): int;
}
class AddStrategy implements Strategy {
public function execute(int $a, int $b): int {
return $a + $b;
}
}
// Your code here
Solution
Step 1: Check interface method signature
The interface requiresexecute(int $a, int $b): intwith type hints and return type.Step 2: Match method signature exactly in SubtractStrategy
class SubtractStrategy implements Strategy { public function execute(int $a, int $b): int { return $a - $b; } } matches the interface exactly with parameter types and return type. class SubtractStrategy { public function execute(int $a, int $b): int { return $a - $b; } } misses implementing the interface. class SubtractStrategy implements Strategy { public function execute(int $a, int $b) { return $a - $b; } } misses return type. class SubtractStrategy implements Strategy { public function execute($a, $b): int { return $a - $b; } } misses parameter types.Final Answer:
class SubtractStrategy implements Strategy { public function execute(int $a, int $b): int { return $a - $b; } } -> Option AQuick Check:
Implement interface with exact method signature [OK]
- Omitting interface implementation
- Missing type hints or return types
- Changing method signature
Ready to prove it?
Pass the test and this pattern moves unknown
