Introducció al Patró State
El patró State és un patró de disseny de comportament que permet a un objecte canviar el seu comportament quan el seu estat intern canvia. Aquest patró és especialment útil quan un objecte ha de canviar el seu comportament en funció del seu estat, i aquests canvis de comportament són complexos o nombrosos.
Conceptes Clau
- Context: L'objecte que conté l'estat actual i delega el comportament a l'estat.
- State: Una interfície o classe abstracta que defineix el comportament associat a un estat particular del context.
- Concrete States: Implementacions concretes de la interfície State que defineixen el comportament específic per a un estat particular.
Diagrama UML
+-----------------+ +-----------------+ | Context | | State | +-----------------+ +-----------------+ | - state: State |<>--------| + handle(): void| +-----------------+ +-----------------+ | + request(): void| +-----------------+ +-----------------+ ^ | | +-----------------+ | ConcreteStateA | +-----------------+ | + handle(): void| +-----------------+ ^ | +-----------------+ | ConcreteStateB | +-----------------+ | + handle(): void| +-----------------+
Exemple Pràctic
Suposem que estem desenvolupant una màquina de cafè que té diferents estats: Ready
, Brewing
, i OutOfService
. Cada estat té un comportament diferent quan es prem el botó de començar.
Implementació en Java
// Interfície State interface State { void handleRequest(); } // Estat concret: Ready class ReadyState implements State { private CoffeeMachine coffeeMachine; public ReadyState(CoffeeMachine coffeeMachine) { this.coffeeMachine = coffeeMachine; } @Override public void handleRequest() { System.out.println("Starting the brewing process..."); coffeeMachine.setState(coffeeMachine.getBrewingState()); } } // Estat concret: Brewing class BrewingState implements State { private CoffeeMachine coffeeMachine; public BrewingState(CoffeeMachine coffeeMachine) { this.coffeeMachine = coffeeMachine; } @Override public void handleRequest() { System.out.println("Already brewing coffee..."); } } // Estat concret: OutOfService class OutOfServiceState implements State { private CoffeeMachine coffeeMachine; public OutOfServiceState(CoffeeMachine coffeeMachine) { this.coffeeMachine = coffeeMachine; } @Override public void handleRequest() { System.out.println("Machine is out of service."); } } // Context: CoffeeMachine class CoffeeMachine { private State readyState; private State brewingState; private State outOfServiceState; private State currentState; public CoffeeMachine() { readyState = new ReadyState(this); brewingState = new BrewingState(this); outOfServiceState = new OutOfServiceState(this); currentState = readyState; // Initial state } public void setState(State state) { currentState = state; } public void pressButton() { currentState.handleRequest(); } public State getReadyState() { return readyState; } public State getBrewingState() { return brewingState; } public State getOutOfServiceState() { return outOfServiceState; } } // Client public class StatePatternDemo { public static void main(String[] args) { CoffeeMachine coffeeMachine = new CoffeeMachine(); coffeeMachine.pressButton(); // Starting the brewing process... coffeeMachine.pressButton(); // Already brewing coffee... coffeeMachine.setState(coffeeMachine.getOutOfServiceState()); coffeeMachine.pressButton(); // Machine is out of service. } }
Exercici Pràctic
Enunciat
Implementa un sistema de semàfor utilitzant el patró State. El semàfor ha de tenir tres estats: Red
, Yellow
, i Green
. Cada estat ha de tenir un comportament diferent quan es canvia l'estat.
Solució
// Interfície State interface TrafficLightState { void change(TrafficLight trafficLight); } // Estat concret: Red class RedState implements TrafficLightState { @Override public void change(TrafficLight trafficLight) { System.out.println("Changing from Red to Green..."); trafficLight.setState(new GreenState()); } } // Estat concret: Yellow class YellowState implements TrafficLightState { @Override public void change(TrafficLight trafficLight) { System.out.println("Changing from Yellow to Red..."); trafficLight.setState(new RedState()); } } // Estat concret: Green class GreenState implements TrafficLightState { @Override public void change(TrafficLight trafficLight) { System.out.println("Changing from Green to Yellow..."); trafficLight.setState(new YellowState()); } } // Context: TrafficLight class TrafficLight { private TrafficLightState state; public TrafficLight() { state = new RedState(); // Initial state } public void setState(TrafficLightState state) { this.state = state; } public void change() { state.change(this); } } // Client public class TrafficLightDemo { public static void main(String[] args) { TrafficLight trafficLight = new TrafficLight(); trafficLight.change(); // Changing from Red to Green... trafficLight.change(); // Changing from Green to Yellow... trafficLight.change(); // Changing from Yellow to Red... } }
Errors Comuns i Consells
- No encapsular l'estat: Assegura't que l'estat estigui encapsulat dins del context i que només es pugui canviar a través de mètodes definits.
- No definir comportaments específics en el context: Mantingues els comportaments específics dins de les classes d'estat concret per seguir el principi de responsabilitat única.
- No gestionar correctament les transicions d'estat: Assegura't que les transicions d'estat siguin clares i gestionades adequadament per evitar inconsistències.
Resum
El patró State permet que un objecte canviï el seu comportament quan el seu estat intern canvia. Aquest patró és útil per gestionar comportaments complexos que depenen de l'estat de l'objecte. Hem vist un exemple pràctic amb una màquina de cafè i un exercici amb un sistema de semàfor. A més, hem destacat alguns errors comuns i consells per evitar-los.
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