状态模式:
允许对象在内部状态改变时改变它的行为,对象看起来好像是修改它的类。
1. 将状态封装成独立的类,并将动作委托到代表当前状态的对象,行为会随着内部状态而改变。 一个状态代表一种行为。
2. 如果使用的对象能够完全改变它的行为,用户觉得这个对象是从别的类实例化得到。实际上,我们使用组合,通过简单引用不同的状态对象来造成类改变的假象。
使用状态模式的优点: 随着软件的升级,可以满足增加的不同状态的需求,只需要扩展一个新的状态。如果使用原始的int类型标识,会造成使用一堆if else判断,且代码不容易维护,也违反 针对接口编程,不针对实现编程 原则。
状态模式的定义:
下面我们使用一个糖果机售卖系统来说明状态模式的使用:
包含的状态:
卖光、未投币、投币、售卖(单个商品)、大赢家(1/10概率得到2个商品).
类图:
相互作用图:
下面是实现源码:
1. GumballMachineTestDrive 主函数入口
public class GumballMachineTestDrive {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
GumballMachine gumballMachine = new GumballMachine(10);
for(int i=0;i<10;i++){
System.out.println(gumballMachine);
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
System.out.println("");
}
System.out.println(gumballMachine);
}
}
2. 定义状态模式接口 State
public interface State {
public void insertQuarter(); // 投入硬币
public void ejectQuarter(); // 拔出硬币
public void turnCrank(); // 摇动抽奖手柄
public void dispense(); // 发放将球
}
3. 实现状态接口的不同状态类
3.1 卖光状态
public class SoldOutState implements State {
GumballMachine mGumballMachine;
public SoldOutState(GumballMachine gumballMachine){
mGumballMachine = gumballMachine;
}
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("SoldOutState : No things to be sold, can't insert a quarter!");
}
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("SoldOutState : No things to be sold, can't eject a quarter!");
}
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("SoldOutState : No things to be sold, can't turn crank!");
}
public void dispense() {
// TODO Auto-generated method stub
System.out.println("SoldOutState : No things to be sold, can't dispense!");
}
}
3.2 未投币状态
public class NoQuarterState implements State {3.3 投币状态
GumballMachine mGumballMachine;
public NoQuarterState(GumballMachine gumballMachine){
mGumballMachine = gumballMachine;
}
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("NoQuarterState : You insert a quarter!");
mGumballMachine.setState(mGumballMachine.getHasQuarterState());
}
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("NoQuarterState : No quarter, cannot eject quarter!");
}
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("NoQuarterState : No quarter, cannot turn crank!");
}
public void dispense() {
// TODO Auto-generated method stub
System.out.println("NoQuarterState : No quarter, cannot dispense!");
}
}
import java.util.Random;3.4 售卖状态
public class HasQuarterState implements State {
Random randomWinner = new Random(System.currentTimeMillis());
GumballMachine mGumballMachine;
public HasQuarterState(GumballMachine gumballMachine){
mGumballMachine = gumballMachine;
}
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("HasQuarterState : You have inserted a quarter, can't again insert!");
}
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("HasQuarterState : You eject a quarter!");
mGumballMachine.setState(mGumballMachine.getNoQuarterState());
}
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("HasQuarterState : You trun crank!");
int winner = randomWinner.nextInt(10);
if(winner==5 && mGumballMachine.getCount() > 1){
mGumballMachine.setState(mGumballMachine.getWinnerState());
}else{
mGumballMachine.setState(mGumballMachine.getSoldState());
}
}
public void dispense() {
// TODO Auto-generated method stub
System.out.println("HasQuarterState : You must trun crank before dispensing first!");
}
}
public class SoldState implements State {3.5 大赢家状态(与售卖状态是平行级别)
GumballMachine mGumballMachine;
public SoldState(GumballMachine gumballMachine){
mGumballMachine = gumballMachine;
}
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("SoldState : You can't insert a quarter!");
}
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("SoldState : You can't eject a quarter!");
}
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("SoldState : You can't turn crank!");
}
public void dispense() {
// TODO Auto-generated method stub
System.out.println("SoldState : You dispense!");
mGumballMachine.releaseBall();
if(mGumballMachine.getCount() > 0){
mGumballMachine.setState(mGumballMachine.getNoQuarterState());
}else{
mGumballMachine.setState(mGumballMachine.getSoldOutState());
}
}
}
public class WinnerState implements State {
GumballMachine mGumballMachine;
public WinnerState(GumballMachine gumballMachine){
mGumballMachine = gumballMachine;
}
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("WinnerState : You can't insert a quarter!");
}
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("WinnerState : You can't eject a quarter!");
}
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("WinnerState : You can't turn crank!");
}
public void dispense() {
// TODO Auto-generated method stub
System.out.println("WinnerState : You are a Winner! you get two gumballs for you quarter!");
mGumballMachine.releaseBall();
if(mGumballMachine.getCount() > 0){
mGumballMachine.releaseBall();
if(mGumballMachine.getCount() > 0){
mGumballMachine.setState(mGumballMachine.getNoQuarterState());
}else{
System.out.println("WinnerState : Oops, out of gumballs!");
mGumballMachine.setState(mGumballMachine.getSoldOutState());
}
}else{
mGumballMachine.setState(mGumballMachine.getSoldOutState());
}
}
}
4. 糖果机机器
public class GumballMachine {
private State soldOutState;
private State noQuarterState;
private State hasQuarterState;
private State soldState;
private State winnerState; //表示十分之一的概率抽到两个球,成为人生大赢家
private State mState;
private int mCount = 0;
public GumballMachine(int count){
mCount = count;
soldOutState = new SoldOutState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState= new SoldState(this);
winnerState = new WinnerState(this);
mState = soldOutState;
if(mCount > 0){
mState = noQuarterState;
}
}
public void setState(State state){
mState = state;
}
public State getState(){
return mState;
}
public State getSoldOutState() {
return soldOutState;
}
public State getNoQuarterState() {
return noQuarterState;
}
public State getHasQuarterState() {
return hasQuarterState;
}
public State getSoldState() {
return soldState;
}
public State getWinnerState() {
return winnerState;
}
public int getCount(){
return mCount;
}
public void insertQuarter(){
mState.insertQuarter();
}
public void ejectQuarter(){
mState.ejectQuarter();
}
public void turnCrank(){
mState.turnCrank();
mState.dispense();
}
public void releaseBall(){
System.out.println("A gumball comes rolling out the slot ...");
if(mCount>0){
mCount -- ;
}
}
}
运行结果:
GumballMachine@7852e922
NoQuarterState : You insert a quarter!
HasQuarterState : You trun crank!
SoldState : You dispense!
A gumball comes rolling out the slot ...
GumballMachine@7852e922
NoQuarterState : You insert a quarter!
HasQuarterState : You trun crank!
SoldState : You dispense!
A gumball comes rolling out the slot ...
GumballMachine@7852e922
NoQuarterState : You insert a quarter!
HasQuarterState : You trun crank!
SoldState : You dispense!
A gumball comes rolling out the slot ...
GumballMachine@7852e922
NoQuarterState : You insert a quarter!
HasQuarterState : You trun crank!
SoldState : You dispense!
A gumball comes rolling out the slot ...
GumballMachine@7852e922
NoQuarterState : You insert a quarter!
HasQuarterState : You trun crank!
SoldState : You dispense!
A gumball comes rolling out the slot ...
GumballMachine@7852e922
NoQuarterState : You insert a quarter!
HasQuarterState : You trun crank!
SoldState : You dispense!
A gumball comes rolling out the slot ...
GumballMachine@7852e922
NoQuarterState : You insert a quarter!
HasQuarterState : You trun crank!
SoldState : You dispense!
A gumball comes rolling out the slot ...
GumballMachine@7852e922
NoQuarterState : You insert a quarter!
HasQuarterState : You trun crank!
SoldState : You dispense!
A gumball comes rolling out the slot ...
GumballMachine@7852e922
NoQuarterState : You insert a quarter!
HasQuarterState : You trun crank!
WinnerState : You are a Winner! you get two gumballs for you quarter!
A gumball comes rolling out the slot ...
A gumball comes rolling out the slot ...
WinnerState : Oops, out of gumballs!
GumballMachine@7852e922
SoldOutState : No things to be sold, can't insert a quarter!
SoldOutState : No things to be sold, can't turn crank!
SoldOutState : No things to be sold, can't dispense!
GumballMachine@7852e922