Introducció al Patró Strategy
El patró de disseny Strategy és un patró de comportament que permet definir una família d'algoritmes, encapsular-los i fer-los intercanviables. Aquest patró permet que l'algoritme variï independentment dels clients que l'utilitzen. És especialment útil quan es vol evitar múltiples condicions if-else o switch-case per seleccionar diferents comportaments.
Objectius del Patró Strategy
- Encapsulació d'algoritmes: Permet encapsular diferents algoritmes dins de classes separades.
- Intercanviabilitat: Facilita la substitució d'un algoritme per un altre sense modificar el codi client.
- Flexibilitat: Permet afegir nous algoritmes sense canviar el codi existent.
Estructura del Patró Strategy
El patró Strategy es compon de tres elements principals:
- Context: Manté una referència a l'objecte Strategy i delega el comportament a aquest objecte.
- Strategy: Defineix una interfície comuna per a tots els algoritmes.
- ConcreteStrategy: Implementa l'algoritme específic seguint la interfície Strategy.
Diagrama UML
+----------------+ +----------------+ | Context | | Strategy | |----------------| |----------------| | - strategy: |<>---->| + algorithm() | | Strategy | +----------------+ |----------------| /_\ | + setStrategy()| | | + execute() | | +----------------+ | | | +---------------------+ | ConcreteStrategyA | |---------------------| | + algorithm() | +---------------------+ +---------------------+ | ConcreteStrategyB | |---------------------| | + algorithm() | +---------------------+
Exemple Pràctic
Definició de la Interfície Strategy
Implementació de ConcreteStrategy
// ConcreteStrategyA.java public class ConcreteStrategyA implements Strategy { @Override public void execute() { System.out.println("Algoritme A executat"); } } // ConcreteStrategyB.java public class ConcreteStrategyB implements Strategy { @Override public void execute() { System.out.println("Algoritme B executat"); } }
Implementació del Context
// Context.java public class Context { private Strategy strategy; public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void executeStrategy() { strategy.execute(); } }
Ús del Patró Strategy
public class StrategyPatternDemo { public static void main(String[] args) { Context context = new Context(); // Utilitzar ConcreteStrategyA context.setStrategy(new ConcreteStrategyA()); context.executeStrategy(); // Sortida: Algoritme A executat // Utilitzar ConcreteStrategyB context.setStrategy(new ConcreteStrategyB()); context.executeStrategy(); // Sortida: Algoritme B executat } }
Exercici Pràctic
Enunciat
Implementa un sistema de càlcul de descomptes utilitzant el patró Strategy. El sistema ha de permetre aplicar diferents tipus de descomptes (per exemple, descompte per percentatge, descompte fix, descompte per quantitat).
Solució
Definició de la Interfície Strategy
Implementació de ConcreteStrategy
// PercentageDiscountStrategy.java public class PercentageDiscountStrategy implements DiscountStrategy { private double percentage; public PercentageDiscountStrategy(double percentage) { this.percentage = percentage; } @Override public double applyDiscount(double price) { return price - (price * (percentage / 100)); } } // FixedDiscountStrategy.java public class FixedDiscountStrategy implements DiscountStrategy { private double discount; public FixedDiscountStrategy(double discount) { this.discount = discount; } @Override public double applyDiscount(double price) { return price - discount; } } // QuantityDiscountStrategy.java public class QuantityDiscountStrategy implements DiscountStrategy { private int quantity; private double discount; public QuantityDiscountStrategy(int quantity, double discount) { this.quantity = quantity; this.discount = discount; } @Override public double applyDiscount(double price) { return price - (quantity * discount); } }
Implementació del Context
// ShoppingCart.java public class ShoppingCart { private DiscountStrategy discountStrategy; public void setDiscountStrategy(DiscountStrategy discountStrategy) { this.discountStrategy = discountStrategy; } public double calculateTotal(double price) { return discountStrategy.applyDiscount(price); } }
Ús del Patró Strategy
public class StrategyPatternDiscountDemo { public static void main(String[] args) { ShoppingCart cart = new ShoppingCart(); // Aplicar descompte per percentatge cart.setDiscountStrategy(new PercentageDiscountStrategy(10)); System.out.println("Total amb descompte per percentatge: " + cart.calculateTotal(100)); // Sortida: 90.0 // Aplicar descompte fix cart.setDiscountStrategy(new FixedDiscountStrategy(15)); System.out.println("Total amb descompte fix: " + cart.calculateTotal(100)); // Sortida: 85.0 // Aplicar descompte per quantitat cart.setDiscountStrategy(new QuantityDiscountStrategy(2, 5)); System.out.println("Total amb descompte per quantitat: " + cart.calculateTotal(100)); // Sortida: 90.0 } }
Errors Comuns i Consells
- No encapsular l'algoritme: Assegura't que cada algoritme estigui encapsulat en una classe separada que implementi la interfície Strategy.
- No utilitzar la interfície Strategy: El context ha de dependre de la interfície Strategy, no de les implementacions concretes.
- No permetre la intercanviabilitat: Assegura't que el context pugui canviar fàcilment d'algoritme en temps d'execució.
Resum
El patró Strategy és una eina poderosa per gestionar diferents algoritmes de manera flexible i intercanviable. Permet encapsular comportaments i seleccionar-los en temps d'execució, millorant la modularitat i mantenibilitat del codi. Amb aquest patró, pots afegir nous algoritmes sense modificar el codi existent, seguint el principi de tancament per modificació i obertura per extensió.
Curs de Patrons de Disseny de Programari
Mòdul 1: Introducció als Patrons de Disseny
- Què són els Patrons de Disseny?
- Història i Origen dels Patrons de Disseny
- Classificació dels Patrons de Disseny
- Avantatges i Desavantatges d'Usar Patrons de Disseny
Mòdul 2: Patrons Creacionals
Mòdul 3: Patrons Estructurals
Mòdul 4: Patrons de Comportament
- Introducció als Patrons de Comportament
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
Mòdul 5: Aplicació de Patrons de Disseny
- Com Seleccionar el Patró Adequat
- Exemples Pràctics d'Ús de Patrons
- Patrons de Disseny en Projectes Reals
- Refactorització Usant Patrons de Disseny
Mòdul 6: Patrons de Disseny Avançats
- Patrons de Disseny en Arquitectures Modernes
- Patrons de Disseny en Microserveis
- Patrons de Disseny en Sistemes Distribuïts
- Patrons de Disseny en Desenvolupament Àgil