8. 状态(State)

Intent

允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它所属的类。

Class Diagram

设计模式 - 状态 - 图1

Implementation

糖果销售机有多种状态,每种状态下销售机有不同的行为,状态可以发生转移,使得销售机的行为也发生改变。

设计模式 - 状态 - 图2

  1. public interface State {
  2. /**
  3. * 投入 25 分钱
  4. */
  5. void insertQuarter();
  6. /**
  7. * 退回 25 分钱
  8. */
  9. void ejectQuarter();
  10. /**
  11. * 转动曲柄
  12. */
  13. void turnCrank();
  14. /**
  15. * 发放糖果
  16. */
  17. void dispense();
  18. }
  1. public class HasQuarterState implements State {
  2. private GumballMachine gumballMachine;
  3. public HasQuarterState(GumballMachine gumballMachine) {
  4. this.gumballMachine = gumballMachine;
  5. }
  6. @Override
  7. public void insertQuarter() {
  8. System.out.println("You can't insert another quarter");
  9. }
  10. @Override
  11. public void ejectQuarter() {
  12. System.out.println("Quarter returned");
  13. gumballMachine.setState(gumballMachine.getNoQuarterState());
  14. }
  15. @Override
  16. public void turnCrank() {
  17. System.out.println("You turned...");
  18. gumballMachine.setState(gumballMachine.getSoldState());
  19. }
  20. @Override
  21. public void dispense() {
  22. System.out.println("No gumball dispensed");
  23. }
  24. }
  1. public class NoQuarterState implements State {
  2. GumballMachine gumballMachine;
  3. public NoQuarterState(GumballMachine gumballMachine) {
  4. this.gumballMachine = gumballMachine;
  5. }
  6. @Override
  7. public void insertQuarter() {
  8. System.out.println("You insert a quarter");
  9. gumballMachine.setState(gumballMachine.getHasQuarterState());
  10. }
  11. @Override
  12. public void ejectQuarter() {
  13. System.out.println("You haven't insert a quarter");
  14. }
  15. @Override
  16. public void turnCrank() {
  17. System.out.println("You turned, but there's no quarter");
  18. }
  19. @Override
  20. public void dispense() {
  21. System.out.println("You need to pay first");
  22. }
  23. }
  1. public class SoldOutState implements State {
  2. GumballMachine gumballMachine;
  3. public SoldOutState(GumballMachine gumballMachine) {
  4. this.gumballMachine = gumballMachine;
  5. }
  6. @Override
  7. public void insertQuarter() {
  8. System.out.println("You can't insert a quarter, the machine is sold out");
  9. }
  10. @Override
  11. public void ejectQuarter() {
  12. System.out.println("You can't eject, you haven't inserted a quarter yet");
  13. }
  14. @Override
  15. public void turnCrank() {
  16. System.out.println("You turned, but there are no gumballs");
  17. }
  18. @Override
  19. public void dispense() {
  20. System.out.println("No gumball dispensed");
  21. }
  22. }
  1. public class SoldState implements State {
  2. GumballMachine gumballMachine;
  3. public SoldState(GumballMachine gumballMachine) {
  4. this.gumballMachine = gumballMachine;
  5. }
  6. @Override
  7. public void insertQuarter() {
  8. System.out.println("Please wait, we're already giving you a gumball");
  9. }
  10. @Override
  11. public void ejectQuarter() {
  12. System.out.println("Sorry, you already turned the crank");
  13. }
  14. @Override
  15. public void turnCrank() {
  16. System.out.println("Turning twice doesn't get you another gumball!");
  17. }
  18. @Override
  19. public void dispense() {
  20. gumballMachine.releaseBall();
  21. if (gumballMachine.getCount() > 0) {
  22. gumballMachine.setState(gumballMachine.getNoQuarterState());
  23. } else {
  24. System.out.println("Oops, out of gumballs");
  25. gumballMachine.setState(gumballMachine.getSoldOutState());
  26. }
  27. }
  28. }
  1. public class GumballMachine {
  2. private State soldOutState;
  3. private State noQuarterState;
  4. private State hasQuarterState;
  5. private State soldState;
  6. private State state;
  7. private int count = 0;
  8. public GumballMachine(int numberGumballs) {
  9. count = numberGumballs;
  10. soldOutState = new SoldOutState(this);
  11. noQuarterState = new NoQuarterState(this);
  12. hasQuarterState = new HasQuarterState(this);
  13. soldState = new SoldState(this);
  14. if (numberGumballs > 0) {
  15. state = noQuarterState;
  16. } else {
  17. state = soldOutState;
  18. }
  19. }
  20. public void insertQuarter() {
  21. state.insertQuarter();
  22. }
  23. public void ejectQuarter() {
  24. state.ejectQuarter();
  25. }
  26. public void turnCrank() {
  27. state.turnCrank();
  28. state.dispense();
  29. }
  30. public void setState(State state) {
  31. this.state = state;
  32. }
  33. public void releaseBall() {
  34. System.out.println("A gumball comes rolling out the slot...");
  35. if (count != 0) {
  36. count -= 1;
  37. }
  38. }
  39. public State getSoldOutState() {
  40. return soldOutState;
  41. }
  42. public State getNoQuarterState() {
  43. return noQuarterState;
  44. }
  45. public State getHasQuarterState() {
  46. return hasQuarterState;
  47. }
  48. public State getSoldState() {
  49. return soldState;
  50. }
  51. public int getCount() {
  52. return count;
  53. }
  54. }
  1. public class Client {
  2. public static void main(String[] args) {
  3. GumballMachine gumballMachine = new GumballMachine(5);
  4. gumballMachine.insertQuarter();
  5. gumballMachine.turnCrank();
  6. gumballMachine.insertQuarter();
  7. gumballMachine.ejectQuarter();
  8. gumballMachine.turnCrank();
  9. gumballMachine.insertQuarter();
  10. gumballMachine.turnCrank();
  11. gumballMachine.insertQuarter();
  12. gumballMachine.turnCrank();
  13. gumballMachine.ejectQuarter();
  14. gumballMachine.insertQuarter();
  15. gumballMachine.insertQuarter();
  16. gumballMachine.turnCrank();
  17. gumballMachine.insertQuarter();
  18. gumballMachine.turnCrank();
  19. gumballMachine.insertQuarter();
  20. gumballMachine.turnCrank();
  21. }
  22. }
  1. You insert a quarter
  2. You turned...
  3. A gumball comes rolling out the slot...
  4. You insert a quarter
  5. Quarter returned
  6. You turned, but there's no quarter
  7. You need to pay first
  8. You insert a quarter
  9. You turned...
  10. A gumball comes rolling out the slot...
  11. You insert a quarter
  12. You turned...
  13. A gumball comes rolling out the slot...
  14. You haven't insert a quarter
  15. You insert a quarter
  16. You can't insert another quarter
  17. You turned...
  18. A gumball comes rolling out the slot...
  19. You insert a quarter
  20. You turned...
  21. A gumball comes rolling out the slot...
  22. Oops, out of gumballs
  23. You can't insert a quarter, the machine is sold out
  24. You turned, but there are no gumballs
  25. No gumball dispensed

设计模式 - 状态 - 图3