HeadFirst设计模式之状态模式
Posted shamgod
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HeadFirst设计模式之状态模式相关的知识,希望对你有一定的参考价值。
一、
1.
2.The State Pattern allows an object to alter its behavior when its internal state changes. The object will appear to change its class.
3.The State Pattern allows an object to have many different behaviors that are based on its internal state.
4.The Context gets its behavior by delegating to the current state object it is composed with.
5.
Strategy Pattern typically configures Context classes with a behavior or algorithm.State Pattern allows a Context to change its behavior as the state of the Context changes.
二、
这种写法若要增加一个状态时,会修改很多
1.
1 package headfirst.designpatterns.state.gumball; 2 3 public class GumballMachine { 4 5 final static int SOLD_OUT = 0; 6 final static int NO_QUARTER = 1; 7 final static int HAS_QUARTER = 2; 8 final static int SOLD = 3; 9 10 int state = SOLD_OUT; 11 int count = 0; 12 13 public GumballMachine(int count) { 14 this.count = count; 15 if (count > 0) { 16 //if the inventory isn’t zero, the machine enters state NO_QUARTER, 17 //meaning it is waiting for someone to insert a quarter, 18 //otherwise it stays in the SOLD_OUT state. 19 state = NO_QUARTER; 20 } 21 } 22 23 public void insertQuarter() { 24 if (state == HAS_QUARTER) { 25 System.out.println("You can\'t insert another quarter"); 26 } else if (state == NO_QUARTER) { 27 state = HAS_QUARTER; 28 System.out.println("You inserted a quarter"); 29 } else if (state == SOLD_OUT) { 30 System.out.println("You can\'t insert a quarter, the machine is sold out"); 31 } else if (state == SOLD) { 32 System.out.println("Please wait, we\'re already giving you a gumball"); 33 } 34 } 35 36 public void ejectQuarter() { 37 if (state == HAS_QUARTER) { 38 System.out.println("Quarter returned"); 39 state = NO_QUARTER; 40 } else if (state == NO_QUARTER) { 41 System.out.println("You haven\'t inserted a quarter"); 42 } else if (state == SOLD) { 43 System.out.println("Sorry, you already turned the crank"); 44 } else if (state == SOLD_OUT) { 45 System.out.println("You can\'t eject, you haven\'t inserted a quarter yet"); 46 } 47 } 48 49 public void turnCrank() { 50 if (state == SOLD) { 51 System.out.println("Turning twice doesn\'t get you another gumball!"); 52 } else if (state == NO_QUARTER) { 53 System.out.println("You turned but there\'s no quarter"); 54 } else if (state == SOLD_OUT) { 55 System.out.println("You turned, but there are no gumballs"); 56 } else if (state == HAS_QUARTER) { 57 System.out.println("You turned..."); 58 state = SOLD; 59 dispense(); 60 } 61 } 62 63 private void dispense() { 64 if (state == SOLD) { 65 System.out.println("A gumball comes rolling out the slot"); 66 count = count - 1; 67 if (count == 0) { 68 System.out.println("Oops, out of gumballs!"); 69 state = SOLD_OUT; 70 } else { 71 state = NO_QUARTER; 72 } 73 } else if (state == NO_QUARTER) { 74 System.out.println("You need to pay first"); 75 } else if (state == SOLD_OUT) { 76 System.out.println("No gumball dispensed"); 77 } else if (state == HAS_QUARTER) { 78 System.out.println("No gumball dispensed"); 79 } 80 } 81 82 public void refill(int numGumBalls) { 83 this.count = numGumBalls; 84 state = NO_QUARTER; 85 } 86 87 public String toString() { 88 StringBuffer result = new StringBuffer(); 89 result.append("\\nMighty Gumball, Inc."); 90 result.append("\\nJava-enabled Standing Gumball Model #2004\\n"); 91 result.append("Inventory: " + count + " gumball"); 92 if (count != 1) { 93 result.append("s"); 94 } 95 result.append("\\nMachine is "); 96 if (state == SOLD_OUT) { 97 result.append("sold out"); 98 } else if (state == NO_QUARTER) { 99 result.append("waiting for quarter"); 100 } else if (state == HAS_QUARTER) { 101 result.append("waiting for turn of crank"); 102 } else if (state == SOLD) { 103 result.append("delivering a gumball"); 104 } 105 result.append("\\n"); 106 return result.toString(); 107 } 108 }
2.
1 package headfirst.designpatterns.state.gumball; 2 3 public class GumballMachineTestDrive { 4 5 public static void main(String[] args) { 6 GumballMachine gumballMachine = new GumballMachine(5); 7 8 System.out.println(gumballMachine); 9 10 gumballMachine.insertQuarter(); 11 gumballMachine.turnCrank(); 12 13 System.out.println(gumballMachine); 14 15 gumballMachine.insertQuarter(); 16 gumballMachine.ejectQuarter(); 17 gumballMachine.turnCrank(); 18 19 System.out.println(gumballMachine); 20 21 gumballMachine.insertQuarter(); 22 gumballMachine.turnCrank(); 23 gumballMachine.insertQuarter(); 24 gumballMachine.turnCrank(); 25 gumballMachine.ejectQuarter(); 26 27 System.out.println(gumballMachine); 28 29 gumballMachine.insertQuarter(); 30 gumballMachine.insertQuarter(); 31 gumballMachine.turnCrank(); 32 gumballMachine.insertQuarter(); 33 gumballMachine.turnCrank(); 34 gumballMachine.insertQuarter(); 35 gumballMachine.turnCrank(); 36 37 System.out.println(gumballMachine); 38 } 39 }
三、
1.
It looks like we’ve got a new plan: instead of maintaining our existing code, we’re going to
rework it to encapsulate state objects in their own classes and then delegate to the current
state when an action occurs.
We’re following our design principles here, so we should end up with a design that is easier to
maintain down the road. Here’s how we’re going to do it:
First, we’re going to define a State interface that
contains a method for every action in the Gumball
Machine.
Then we’re going to implement a State class for
every state of the machine. These classes will be
responsible for the behavior of the machine when it
is in the corresponding state.
Finally, we’re going to get rid of all of our conditional
code and instead delegate to the state class to do
the work for us.
2.
3.
4.
5.
6.
四、
1.
1 package headfirst.designpatterns.state.gumballstatewinner; 2 3 public interface State { 4 5 public void insertQuarter(); 6 public void ejectQuarter(); 7 public void turnCrank(); 8 public void dispense(); 9 10 public void refill(); 11 }
2.
1 package headfirst.designpatterns.state.gumballstatewinner; 2 3 import java.util.Random; 4 5 public class HasQuarterState implements State { 6 Random randomWinner = new Random(System.currentTimeMillis()); 7 GumballMachine gumballMachine; 8 9 public HasQuarterState(GumballMachine gumballMachine) { 10 this.gumballMachine = gumballMachine; 11 } 12 13 public void insertQuarter() { 14 System.out.println("You can\'t insert another quarter"); 15 } 16 17 public void ejectQuarter() { 18 System.out.println("Quarter returned"); 19 gumballMachine.setState(gumballMachine.getNoQuarterState()); 20 } 21 22 public void turnCrank() { 23 System.out.println("You turned..."); 24 int winner = randomWinner.nextInt(10); 25 if ((winner == 0) && (gumballMachine.getCount() > 1)) { 26 gumballMachine.setState(gumballMachine.getWinnerState()); 27 } else { 28 gumballMachine.setState(gumballMachine.getSoldState()); 29 } 30 } 31 32 public void dispense() { 33 System.out.println("No gumball dispensed"); 34 } 35 36 public void refill() { } 37 38 public String toString() { 39 return "waiting for turn of crank"; 40 } 41 }
3.
1 package headfirst.designpatterns.state.gumballstatewinner; 2 3 public class NoQuarterState implements State { 4 GumballMachine gumballMachine; 5 6 public NoQuarterState(GumballMachine gumballMachine) { 7 this.gumballMachine = gumballMachine; 8 } 9 10 public void insertQuarter() { 11 System.out.println("You inserted a quarter"); 12 gumballMachine.setState(gumballMachine.getHasQuarterState()); 13 } 14 15 public void ejectQuarter() { 16 System.out.println("You haven\'t inserted a quarter"); 17 } 18 19 public void turnCrank() { 20 System.out.println("You turned, but there\'s no quarter"); 21 } 22 23 public void dispense() { 24 System.out.println("You need to pay first"); 25 } 26 27 public void refill() { } 28 29 public String toString() { 30 return "waiting for quarter"; 31 } 32 }
4.
1 package headfirst.designpatterns.state.gumballstatewinner; 2 3 public class SoldOutState implements State { 4 GumballMachine gumballMachine; 5 6 public SoldOutState(GumballMachine gumballMachine) { 7 this.gumballMachine = gumballMachine; 8 } 9 10 public void insertQuarter() { 11 System.out.println("You can\'t insert a quarter, the machine is sold out"); 12 } 13 14 public void ejectQuarter() { 15 System.out.println("You can\'t eject, you haven\'t inserted a quarter yet"); 16 } 17 18 public void turnCrank() { 19 System.out.println("You turned, but there are no gumballs"); 20 } 21 22 public void dispense() { 23 System.out.println("No gumball dispensed"); 24 } 25 26 public void refill() { 27 gumballMachine.setState(gumballMachine.getNoQuarterState()); 28 } 29 30 public String toString() { 31 return "sold out"; 32 } 33 }
5.
1 package headfirst.designpatterns.state.gumballstatewinner; 2 3 public class SoldState implements State { 4 GumballMachine gumballMachine; 5 6 public SoldState(GumballMachine gumballMachine) { 7 this.gumballMachine = gumballMachine; 8 } 9 10 public void insertQuarter() { 11 System.out.println("Please wait, we\'re already giving you a gumball"); 12 } 13 14 public void ejectQuarter() { 15 System.out.println("Sorry, you already turned the crank"); 16 } 17 18 public void turnCrank() { 19 System.out.println("Turning twice doesn\'t get you another gumball!"); 20 } 21 22 public void dispense() { 23 gumballMachine.releaseBall(); 24 if (gumballMachine.getCount() > 0) { 25 gumballMachine.setState(gumballMachine.getNoQuarterState()); 26 } else { 27 System.out.println("Oops, out of gumballs!"); 28 gumballMachine.setState(gumballMachine.getSoldOutState()); 29 } 30 } 31 32 public void refill() { } 33 34 public String toString() { 35 return "dispensing a gumball"; 36 } 37 }
6.
1 package headfirst.designpatterns.state.gumballstatewinner; 2 3 public class WinnerState implements State { 4 GumballMachine gumballMachine; 5 6 public WinnerState(GumballMachine gumballMachine) { 7 this.gumballMachine = gumballMachine; 8 } 9 10 public void insertQuarter() { 11 System.out.println("Please wait, we\'re already giving you a Gumball"); 12 } 13 14 public void ejectQuarter() { 15 System.out.println("Please wait, we\'re already giving you a Gumball"); 16 } 17 18 public void turnCrank() { 19 System.out.println("Turning again doesn\'t get you another gumball!"); 20 } 21 22 public void dispense() { 23 gumballMachine.releaseBall(); 24 if (gumballMachine.getCount() == 0) { 25 gumballMachine.setState(gumballMachine.getSoldOutState()); 26 } else { 27 gumballMachine.releaseBall(); 28 System.out.println("YOU\'RE A WINNER! You got two gumballs for your quarter"); 29 if (gumballMachine.getCount() > 0) { 30 gumballMachine.setState(gumballMachine.getNoQuarterState()); 31 } else { 32 System.out.println("Oops, out of gumballs!"); 33 gumballMachine.setState(gumballMachine.getSoldOutState()); 34 } 35 } 36 } 37 38 public void refill() { } 39 40 public String toString() { 41 return "despensing two gumballs for your quarter, because YOU\'RE A WINNER!"; 42 } 43 }
7.
1 package headfirst.designpatterns.state.gumballstatewinner; 2 3 public class GumballMachine { 4 5 State soldOutState; 6 State noQuarterState; 7 State hasQuarterState; 8 State soldState; 9 State winnerState; 10 11 State state = soldOutState; 12 int count = 0; 13 14 public GumballMachine(int numberGumballs) { 15 soldOutState = new SoldOutState(this); 16 noQuarterState = new NoQuarterState(this); 17 hasQuarterState = new HasQuarterState(this); 18 soldState = new SoldState(this); 19 winnerState = new WinnerState(this); 20 21 this.count = numberGumballs; 22 if (numberGumballs > 0) { 23 state = noQuarterState; 24 } 25 } 26 27 public void insertQuarter() { 28 state.insertQuarter(); 29 } 30 31 public void ejectQuarter() { 32 state.ejectQuarter(); 33 } 34 35 public void turnCrank() { 36 state.turnCrank(); 37 state.dispense(); 38 } 39 40 void setState(State state) { 41 this.state = state; 42 } 43 44 void releaseBall() { 45 System.out.println("A gumball comes rolling out the slot..."); 46 if (count != 0) { 47 count = count - 1; 48 } 49 } 50 51 int getCount() { 52 return count; 53 } 54 55 void refill(int count) { 56 this.count += count; 57 System.out.println("The gumball machine was just refilled; it\'s new count is: " + this.count); 58 state.refill(); 59 } 60 61 public State getState() { 62 return state; 63 } 64 65 public State getSoldOutState() { 66 return soldOutState; 67 } 68 69 以上是关于HeadFirst设计模式之状态模式的主要内容,如果未能解决你的问题,请参考以下文章