Design Pattern – Strategy
Suponha que você tenha criado um relatório no sistema e o cliente precise exportar os dados para diferentes formatos, como CSV e JSON.
Embora a ação seja a mesma (exportar dados) o algoritmo utilizado para gerar cada formato é diferente.
Uma solução simples seria usar vários if ou switch, mas isso violaria o princípio Open/Closed e dificultaria a manutenção do código.
É exatamente nesse cenário que o Strategy Pattern se torna útil.
O Strategy permite encapsular diferentes algoritmos em classes separadas e torná-los intercambiáveis em tempo de execução. Assim, o comportamento pode variar sem modificar a classe que o utiliza.

A classe de contexto (FileExporter) não define por si só a estratégia (CsvFormat ou JsonFormat) que será utilizada. Quem define a estratégia em tempo de execução é o cliente através do método setFormat, que recebe um objeto que implementa a interface IOutputFormat e realiza a exportação dos dados através do método export.
Implementando as estratégias
Primeiro definimos a interface que servirá de base comum para nossas estratégias, a interface IOutputFormat.
<?php
namespace App\Tools\FileExporter;
interface IOutputFormat
{
public function export(string $fileName, array $data): void;
}Code language: PHP (php)
Em seguida as classes concretas referentes aos algoritmos de importação.
CSV
<?php
namespace App\Tools\FileExporter;
final class CsvFormat implements IOutputFormat
{
public function export(string $fileName, array $data):void
{
$csvArrayData[] = array_keys($data[0]);
foreach($data as $key => $value){
$csvArrayData[] = array_values($value);
}
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="'.$fileName.'.csv"');
header('X-Content-Type-Options: nosniff');
$fp = fopen('php://output', 'w');
foreach($csvArrayData as $row){
fputcsv($fp, $row);
}
fclose($fp);
exit;
}
}Code language: PHP (php)
Json
<?php
namespace App\Tools\FileExporter;
final class JsonFormat implements IOutputFormat
{
public function export(string $fileName, array $data):void
{
$content = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
header('Content-Type: application/json; charset=UTF-8');
header('Content-Disposition: attachment; filename="'.$fileName.'.json"');
header('Content-Length: ' . strlen($content));
header('X-Content-Type-Options: nosniff');
echo $content;
exit;
}
}Code language: PHP (php)
Agora a classe de contexto:
<?php
namespace App\Tools\FileExporter;
class FileExporter
{
private IOutputFormat $outputFormat;
public function __construct(IOutputFormat $outputFormat){
$this->outputFormat = $outputFormat;
}
public function export(string $fileName, array $data): void
{
$this->outputFormat->build($fileName, $data);
}
public function setFormat(IOutputFormat $outputFormat): void
{
$this->outputFormat = $outputFormat;
}
}Code language: PHP (php)
O Strategy Pattern é especialmente útil quando diferentes variações de um comportamento precisam coexistir no sistema sem acoplamento forte entre as implementações.
Além de melhorar a organização do código, esse padrão facilita a extensão da aplicação. Para adicionar um novo formato de exportação, como XML ou XLSX, basta criar uma nova classe que implemente IOutputFormat, sem modificar o FileExporter.
Esse é um exemplo claro de aplicação do princípio Open/Closed.