From ab4e53a468fe1de6dc0ad731e2308ad80d37465c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Mon, 20 Jul 2020 20:06:39 +0300 Subject: [PATCH] #590 add explanation for State --- state/README.md | 122 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 2 deletions(-) diff --git a/state/README.md b/state/README.md index 4f61d3025..7be4d3351 100644 --- a/state/README.md +++ b/state/README.md @@ -12,8 +12,126 @@ tags: Objects for States ## Intent -Allow an object to alter its behavior when its internal state -changes. The object will appear to change its class. +Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. + +## Explanation +Real world example + +> When observing a mammoth in its natural habitat it seems to change its behavior based on the situation. It may first appear calm but over time when it detects a threat it gets angry and dangerous to its surroundings. + +In plain words + +> State pattern allows an object to change its behavior. + +Wikipedia says + +> The state pattern is a behavioral software design pattern that allows an object to alter its behavior when its internal state changes. This pattern is close to the concept of finite-state machines. The state pattern can be interpreted as a strategy pattern, which is able to switch a strategy through invocations of methods defined in the pattern's interface. + +**Programmatic Example** + +Here is the state interface and its concrete implementations. + +```java +public interface State { + + void onEnterState(); + + void observe(); +} + +public class PeacefulState implements State { + + private static final Logger LOGGER = LoggerFactory.getLogger(PeacefulState.class); + + private Mammoth mammoth; + + public PeacefulState(Mammoth mammoth) { + this.mammoth = mammoth; + } + + @Override + public void observe() { + LOGGER.info("{} is calm and peaceful.", mammoth); + } + + @Override + public void onEnterState() { + LOGGER.info("{} calms down.", mammoth); + } +} + +public class AngryState implements State { + + private static final Logger LOGGER = LoggerFactory.getLogger(AngryState.class); + + private Mammoth mammoth; + + public AngryState(Mammoth mammoth) { + this.mammoth = mammoth; + } + + @Override + public void observe() { + LOGGER.info("{} is furious!", mammoth); + } + + @Override + public void onEnterState() { + LOGGER.info("{} gets angry!", mammoth); + } +} +``` + +And here is the mammoth containing the state. + +```java +public class Mammoth { + + private State state; + + public Mammoth() { + state = new PeacefulState(this); + } + + public void timePasses() { + if (state.getClass().equals(PeacefulState.class)) { + changeStateTo(new AngryState(this)); + } else { + changeStateTo(new PeacefulState(this)); + } + } + + private void changeStateTo(State newState) { + this.state = newState; + this.state.onEnterState(); + } + + @Override + public String toString() { + return "The mammoth"; + } + + public void observe() { + this.state.observe(); + } +} +``` + +And here is the full example how the mammoth behaves over time. + +```java + var mammoth = new Mammoth(); + mammoth.observe(); + mammoth.timePasses(); + mammoth.observe(); + mammoth.timePasses(); + mammoth.observe(); + + // The mammoth gets angry! + // The mammoth is furious! + // The mammoth calms down. + // The mammoth is calm and peaceful. +``` ## Class diagram ![alt text](./etc/state_1.png "State")