设计模式 状态模式

时间:2020-11-30 21:59:57

状态模式:

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

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 {

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!");
}

}
3.3 投币状态

import java.util.Random;


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!");
}

}
3.4 售卖状态

public class SoldState implements State {

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());
}

}

}
3.5 大赢家状态(与售卖状态是平行级别)

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