Návrhový vzor strategie (Strategy, Policy) slouží k vyměňování různých implementací algoritmu za běhu programu. Tato záměna může proběhnout buď explicitně (na žádost klienta) nebo implicitně (na základě nastavení ovladače).
Jádrem tohoto vzoru je třída Context, která slouží jako container na jednotlivé postupy. V momentě, kdy dojde k potřebě změny chování, Context prohodí objekty reprezentující dané algoritmy.
Příklad
Mějme pokladnu v baru, pokladna (odpovídá Contextu) umí některé operace, které budou vždy stejné – například vytisknout účtenku, ale zároveň se její chování musí měnit v průběhu času, protože bar pořádá tzv. „Happy hour“, kdy zákazníci mají slevu 10% na jednotlivé nápoje. Z tohoto důvodu je vhodné implementovat chování slev pomocí návrhového vzoru strategie. Tímto se zároveň zajistí snadné přidání dalších akcí do pokladního systému (na vysvědčení pivo pro premianty zdarma atp.).
Kód
/** * Demostrace navrhoveho vzoru Strategie * @author Pavel Micka */ public class StrategyDemonstration { public static void main(String[] args){ CashDesk c = new CashDesk(); c.setStrategy(new HappyHourStrategy()); c.add(20); c.add(80); c.printBill(); //Konec Happy Hour c.setStrategy(new NormalStrategy()); c.add(20); c.add(80); c.printBill(); } } /** * Pokladna (Context) * @author Pavel Micka */ class CashDesk{ /** * Sem se uklada utrata */ private List<Integer> drinks; private BillingStrategy strategy; public CashDesk() { this.drinks = new ArrayList<Integer>(); } /** * Prida polozku na ucet * @param price cena polozky */ public void add(int price){ drinks.add(price); } /** * Vytiskne uctenku */ public void printBill(){ System.out.println("Celkem k zaplaceni: " + strategy.sum(drinks)); System.out.println("Dekujeme za navstevu, vratte se znovu!"); drinks.clear(); } /** * Nastavi strategii * @param strategy strategie */ public void setStrategy(BillingStrategy strategy) { this.strategy = strategy; } } /** * Uctovaci strategie * @author Pavel Micka */ interface BillingStrategy{ /** * Vrati celkovou cenu vypitych napoju * @return celkova cena */ public double sum(List<Integer> drinks); } /** * Bezna uctovaci strategie (bezne ceny) * @author Pavel Micka */ class NormalStrategy implements BillingStrategy{ public double sum(List<Integer> drinks) { int sum = 0; for(Integer i : drinks){ sum += i; } return sum; } } /** * Strategie pro Happy hour (sleva 10%) * @author Pavel Micka */ class HappyHourStrategy implements BillingStrategy{ public double sum(List<Integer> drinks) { int sum = 0; for(Integer i : drinks){ sum += i; } return sum*0.9; } }