A strategy minta akkor jön jól, ha van egy osztályunk, aminek a viselkedése eltérő különböző esetekben. Ebben az esetben ezek a viselkedések kiemelhetőek kisebb, önálló osztályokba a minta segítségével.
De pontosan mit is értek az alatt, hogy osztály eltérő viselkedéssel? Képzeljünk el egy saját lista implementációt, ami a benne tárolt elemeket tudja rendezni. Rendezési algoritmusból van egy pár és bizonyos esetekben egyik alkalmazása a másik helyett nem biztos, hogy jobb. A strategy minta segítségével könnyen implementálható az, hogy az elemszám függvényében válasszon rendezési algoritmust a listánk úgy, hogy az egyes algoritmusok külön osztályban kapnak helyet.
Nézzünk egy példát:
internal interface IOperationStrategy
{
double Calculate(double x, double y);
}
internal class AddStrategy : IOperationStrategy
{
public double Calculate(double x, double y)
{
return x + y;
}
}
internal class SubtractStrategy : IOperationStrategy
{
public double Calculate(double x, double y)
{
return x - y;
}
}
internal class MultiplyStrategy : IOperationStrategy
{
public double Calculate(double x, double y)
{
return x * y;
}
}
internal class DivideStrategy : IOperationStrategy
{
public double Calculate(double x, double y)
{
return x / y;
}
}
public class CalculatorContext
{
private IOperationStrategy? _strategy;
public void SetStrategy(char @operator)
{
switch (@operator)
{
case '+':
_strategy = new AddStrategy();
break;
case '-':
_strategy = new SubtractStrategy();
break;
case '*':
_strategy = new MultiplyStrategy();
break;
case '/':
_strategy = new DivideStrategy();
break;
default:
throw new InvalidOperationException($"Invalid operator: {@operator}");
}
}
public double Calculate(double x, double y)
{
if (_strategy == null)
throw new InvalidOperationException("No strategy has been set");
return _strategy.Calculate(x, y);
}
}
A fenti példa egy egyszerű négy művelet végzésére alkalmas számológépet valósít meg, amiben a műveletek egyes implementációi különböző stratégiák. Az IOperationStrategy interfész definiálja a közös interfészt és viselkedést a műveletvégzéshez. A CalculatorContext pedig felhasználja az IOperationStrategy implementációit. A SetStrategy metódus egy műveleti jel alapján kiválasztja a használni kívánt stratégiát. A Calculate metódus pedig elvégzi a számítást.
Előnyök
- Menet közben cserélhetőek vele egy osztály algoritmusai.
- Open/Closed elvet támogatja, mivel új algoritmusok vezethetőek be a meglévőek módosítása nélkül.
- Elválasztja az algoritmus implementációt a felhasználás helyétől.
Hátrányok
- Ha csak pár (1-2) algoritmusunk van, amik nem igen változnak, akkor nincs értelme a bevezetésével túlkomplikálni a kódot
- Hasonló viselkedés elérhető lambda metódusokkal és delegáltakkal is.