目录
状态模式(State Pattern):它主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。状态和行为是一一对应的,状态之间可以相互转换。当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。
状态模式和策略模式区别
1、策略模式封装了一组行为或者算法,它允许Client在运行时动态的切换;状态模式是帮助一个类在不同的状态下显示不同的行为,依赖于内部的状态;
2、策略模式不持有Context的引用,而是被Context所使用;状态模式的每个状态都持有Context的引用,从而在Context中实现状态的转移;
3、从理论上说,策略模式定义对象应该“怎么做”;状态模式定义了对象“是什么”,“什么时候做”。
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
Context 类为环境角色, 用于维护State 实例,这个实例定义当前状态(聚合State)。
State 是抽象状态角色,定义一个接口封装与Context 的一个特点接口相关行为。
ConcreteState 具体的状态角色,每个子类实现一个与Context 的一个状态相关行为。
案例:糖果销售机有多种状态,每种状态下销售机有不同的行为,状态可以发生转移,使得销售机的行为也发生改变。
- public interface State {
- /**
- * 投入 25 分钱
- */
- void insertQuarter();
-
- /**
- * 退回 25 分钱
- */
- void ejectQuarter();
-
- /**
- * 转动曲柄
- */
- void turnCrank();
-
- /**
- * 发放糖果
- */
- void dispense();
- }
- public class HasQuarterState implements State {
- private GumballMachine gumballMachine;
-
- public HasQuarterState(GumballMachine gumballMachine) {
- this.gumballMachine = gumballMachine;
- }
-
- @Override
- public void insertQuarter() {
- System.out.println("You can't insert another quarter");
- }
-
- @Override
- public void ejectQuarter() {
- System.out.println("Quarter returned");
- gumballMachine.setState(gumballMachine.getNoQuarterState());
- }
-
- @Override
- public void turnCrank() {
- System.out.println("You turned...");
- gumballMachine.setState(gumballMachine.getSoldState());
- }
-
- @Override
- public void dispense() {
- System.out.println("No gumball dispensed");
- }
- }
- public class NoQuarterState implements State {
- GumballMachine gumballMachine;
-
- public NoQuarterState(GumballMachine gumballMachine) {
- this.gumballMachine = gumballMachine;
- }
-
- @Override
- public void insertQuarter() {
- System.out.println("You insert a quarter");
- gumballMachine.setState(gumballMachine.getHasQuarterState());
- }
-
- @Override
- public void ejectQuarter() {
- System.out.println("You haven't insert a quarter");
- }
-
- @Override
- public void turnCrank() {
- System.out.println("You turned, but there's no quarter");
- }
-
- @Override
- public void dispense() {
- System.out.println("You need to pay first");
- }
- }
- public class SoldOutState implements State {
- GumballMachine gumballMachine;
-
- public SoldOutState(GumballMachine gumballMachine) {
- this.gumballMachine = gumballMachine;
- }
-
- @Override
- public void insertQuarter() {
- System.out.println("You can't insert a quarter, the machine is sold out");
- }
-
- @Override
- public void ejectQuarter() {
- System.out.println("You can't eject, you haven't inserted a quarter yet");
- }
-
- @Override
- public void turnCrank() {
- System.out.println("You turned, but there are no gumballs");
- }
-
- @Override
- public void dispense() {
- System.out.println("No gumball dispensed");
- }
- }
- public class SoldState implements State {
- GumballMachine gumballMachine;
-
- public SoldState(GumballMachine gumballMachine) {
- this.gumballMachine = gumballMachine;
- }
-
- @Override
- public void insertQuarter() {
- System.out.println("Please wait, we're already giving you a gumball");
- }
-
- @Override
- public void ejectQuarter() {
- System.out.println("Sorry, you already turned the crank");
- }
-
- @Override
- public void turnCrank() {
- System.out.println("Turning twice doesn't get you another gumball!");
- }
-
- @Override
- public void dispense() {
- gumballMachine.releaseBall();
- if (gumballMachine.getCount() > 0) {
- gumballMachine.setState(gumballMachine.getNoQuarterState());
- } else {
- System.out.println("Oops, out of gumballs");
- gumballMachine.setState(gumballMachine.getSoldOutState());
- }
- }
- }
- public class GumballMachine {
- private State soldOutState;
- private State noQuarterState;
- private State hasQuarterState;
- private State soldState;
-
- private State state;
- private int count = 0;
-
- public GumballMachine(int numberGumballs) {
- count = numberGumballs;
- soldOutState = new SoldOutState(this);
- noQuarterState = new NoQuarterState(this);
- hasQuarterState = new HasQuarterState(this);
- soldState = new SoldState(this);
-
- if (numberGumballs > 0) {
- state = noQuarterState;
- } else {
- state = soldOutState;
- }
- }
-
- public void insertQuarter() {
- state.insertQuarter();
- }
-
- public void ejectQuarter() {
- state.ejectQuarter();
- }
-
- public void turnCrank() {
- state.turnCrank();
- state.dispense();
- }
-
- public void setState(State state) {
- this.state = state;
- }
-
- public void releaseBall() {
- System.out.println("A gumball comes rolling out the slot...");
- if (count != 0) {
- count -= 1;
- }
- }
-
- public State getSoldOutState() {
- return soldOutState;
- }
-
- public State getNoQuarterState() {
- return noQuarterState;
- }
-
- public State getHasQuarterState() {
- return hasQuarterState;
- }
-
- public State getSoldState() {
- return soldState;
- }
-
- public int getCount() {
- return count;
- }
- }
- public class Client {
- public static void main(String[] args) {
- GumballMachine gumballMachine = new GumballMachine(5);
-
- gumballMachine.insertQuarter();
- gumballMachine.turnCrank();
-
- gumballMachine.insertQuarter();
- gumballMachine.ejectQuarter();
- gumballMachine.turnCrank();
-
- gumballMachine.insertQuarter();
- gumballMachine.turnCrank();
- gumballMachine.insertQuarter();
- gumballMachine.turnCrank();
- gumballMachine.ejectQuarter();
-
- gumballMachine.insertQuarter();
- gumballMachine.insertQuarter();
- gumballMachine.turnCrank();
- gumballMachine.insertQuarter();
- gumballMachine.turnCrank();
- gumballMachine.insertQuarter();
- gumballMachine.turnCrank();
- }
- }
- You insert a quarter
- You turned...
- A gumball comes rolling out the slot...
- You insert a quarter
- Quarter returned
- You turned, but there's no quarter
- You need to pay first
- You insert a quarter
- You turned...
- A gumball comes rolling out the slot...
- You insert a quarter
- You turned...
- A gumball comes rolling out the slot...
- You haven't insert a quarter
- You insert a quarter
- You can't insert another quarter
- You turned...
- A gumball comes rolling out the slot...
- You insert a quarter
- You turned...
- A gumball comes rolling out the slot...
- Oops, out of gumballs
- You can't insert a quarter, the machine is sold out
- You turned, but there are no gumballs
- No gumball dispensed