状态模式的状态中的方法是促进状态转化的操作,当然也可以包括一些公共的行为,必须几个状态都有disply的方法,那这个方法可以放到抽象状态中。而不是说一种状态对应一个方法,这样理解是不对的。
我的一点思考:感觉,tcpconnection这个适合状态模式、上传下载的状态等等这些都较为适合使用这个模式。
以下是《head first设计模式》上的一个案例:从这个案例中可以看出,insertQuarter、ejectQuarter、turnCrank、dispense这几个方法可以促进状态之间的转化,这些方法对应着接口中的方法。不过每个具体的状态都可以有自己的个性(private方法)。
!!!
状态模式的难点就在于如何设计抽象接口中的几个方法。这才是他的难点所在。
/**
* Created by annuoaichengzhang on 16/4/21.
* 糖果机的案例
*/
public interface State {
public void insertQuarter(); // 投入25分钱
public void ejectQuarter(); // 拒绝25分钱
public void turnCrank(); // 转动曲柄
public void dispense(); // 发放糖果
}
/**
* Created by annuoaichengzhang on 16/4/21.
*/
/*
* 有25分钱状态,实现了State接口
*/
public class HasQuarterState implements State {
Random randomWinner = new Random(System.currentTimeMillis()); //首先我们增加一个随机数产生器,产生10%赢的机
GumballMachine gumballMachine;
public HasQuarterState(GumballMachine gumballMachine){
this.gumballMachine = gumballMachine;
}
// 投入25分钱
public void insertQuarter() {
System.out.println("You can not insert anther quarter");
}
// 拒绝25分钱
public void ejectQuarter() {
System.out.println("Quarter returned");
gumballMachine.setState(gumballMachine.getNoQuarterState());
}
// 转动曲柄
public void turnCrank() {
System.out.println("You turned...");
int winner = randomWinner.nextInt(10);
System.out.println("winner =" + winner);
if((winner ==0) && (gumballMachine.getCount() > 1)) {
gumballMachine.setState(gumballMachine.getWinnerState());
} else {
gumballMachine.setState(gumballMachine.getSoldState());
}
}
// 发放糖果
public void dispense() {
System.out.println("No gumball dispensed");
}
}
/**
* Created by annuoaichengzhang on 16/4/21.
*/
/*
* 没有25分钱状态,实现了State接口
*/
public class NoQuarterState implements State{
GumballMachine gumballMachine;
public NoQuarterState(GumballMachine gumballMachine){
this.gumballMachine=gumballMachine;
}
// 投入25分钱
public void insertQuarter() {
System.out.println("You insert a quarter");
gumballMachine.setState(gumballMachine.getHasQuarterState());
}
// 拒绝25分钱
public void ejectQuarter() {
System.out.println("You haven't insert a quarter");
}
// 转动曲柄
public void turnCrank() {
System.out.println("You turned crank,but you there's no quarter");
}
// 发放糖果
public void dispense() {
System.out.println("You need to pay first");
}
}
/**
* Created by annuoaichengzhang on 16/4/21.
*/
/*
* 通过售罄状态,实现了State接口
*/
public class SoldOutState implements State{
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine){
this.gumballMachine=gumballMachine;
}
// 投入25分钱
public void insertQuarter() {
System.out.println("You can't insert a quarter, the machine is sold out");
}
// 拒绝25分钱
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("You can't eject, you haven't inserted a quarter yet");
}
// 转动曲柄
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("You turned, but there are no gumballs");
}
// 发放糖果
public void dispense() {
// TODO Auto-generated method stub
System.out.println("No gumball dispensed");
}
}
/**
* Created by annuoaichengzhang on 16/4/21.
*/
/*
* 售出糖果状态,实现了State接口
*/
public class SoldState implements State{
GumballMachine gumballMachine;
public SoldState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
// 投入25分钱
public void insertQuarter() {
System.out.println("Please wait, we're already giving you a gumball");
}
// 拒绝25分钱
public void ejectQuarter() {
System.out.println("Sorry,you have already turn crank");
}
// 转动曲柄
public void turnCrank() {
System.out.println("trun twice ,doesn't give you anthor gamball!");
}
// 发放糖果
public void dispense() {
gumballMachine.releaseBall();
if(gumballMachine.getCount()>0){
gumballMachine.setState(gumballMachine.getNoQuarterState());
} else {
System.out.println("Opps,out of gamball!");
gumballMachine.setState(gumballMachine.getSoldOutState());
}
}
}
/**
* Created by annuoaichengzhang on 16/4/21.
*/
/*
* 赢家状态,实现了State接口
*/
public class WinnerState implements State{
GumballMachine gumballMachine;
public WinnerState(GumballMachine gumballMachine){
this.gumballMachine = gumballMachine;
}
// 投入25分钱
@Override
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("Please wait, we're already giving you a gumball");
}
// 拒绝25分钱
@Override
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("Sorry,you have already turn crank");
}
// 转动曲柄
@Override
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("trun twice ,doesn't give you anthor gamball!");
}
// 发放糖果
@Override
public void dispense() {
// TODO Auto-generated method stub
System.out.println("You're a Winner! You get two gumballs for your quarter");
gumballMachine.releaseBall();
if(gumballMachine.getCount() == 0) {
gumballMachine.setState(gumballMachine.getSoldOutState());
} else {
gumballMachine.releaseBall();
if(gumballMachine.getCount()>0){
gumballMachine.setState(gumballMachine.getNoQuarterState());
} else {
System.out.println("Opps,out of gamball!");
gumballMachine.setState(gumballMachine.getSoldOutState());
}
}
}
}
/**
* Created by annuoaichengzhang on 16/4/21.
*/
/*
* 糖果机器上下文环境接口类 GumballMachine
*/
public class GumballMachine {
//状态实例
State soldOutState;
State noQuarterState;
State hasQuarterState;
State soldState;
State winnerState;
// 实例变量state,初始化为糖果售罄状态
State state = soldOutState;
// 记录机器内装有糖果的数目,开始机器是没有装糖果的
int count=0;
// 构造器取得糖果的初始数目并把它放在一个实例变量count中
public GumballMachine(int numberGumballs) {
// 每种状态都创建一个状态实例
soldOutState=new SoldOutState(this);
noQuarterState=new NoQuarterState(this);
hasQuarterState=new HasQuarterState(this);
soldState=new SoldState(this);
winnerState = new WinnerState(this);
this.count = numberGumballs;
// 若超过0颗糖果,就将状态设置为NoQuarterState
if(numberGumballs > 0) {
state = noQuarterState;
}
}
// 取得机器内的糖果数目
public int getCount() {
return count;
}
// 取得糖果售罄状态
public State getSoldOutState() {
return soldOutState;
}
// 取得没有25分钱状态
public State getNoQuarterState() {
return noQuarterState;
}
// 取得拥有25分钱
public State getHasQuarterState() {
return hasQuarterState;
}
// 取得售出糖果状态
public State getSoldState() {
return soldState;
}
// 取得赢家状态
public State getWinnerState() {
return winnerState;
}
// 投入25分钱
public void insertQuarter(){
state.insertQuarter();
}
// 拒绝25分钱
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 of the solt...");
if(count!=0){
count--;
}
}
}
/**
* Created by annuoaichengzhang on 16/4/21.
*/
/*
* 糖果机测试驱动程序:GumballMachineTestDrive.java
*/
public class GumballMachineTestDrive {
/**
* @param args
*/
public static void main(String[] args) {
GumballMachine gumballMachine = new GumballMachine(5);
System.out.println(gumballMachine);
System.out.println("The current gumball number is:" + gumballMachine.getCount());
System.out.println("****************************************");
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
System.out.println(gumballMachine);
System.out.println("The current gumball number is:" + gumballMachine.getCount());
System.out.println("****************************************");
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
System.out.println(gumballMachine);
System.out.println("The current gumball number is:" + gumballMachine.getCount());
System.out.println("****************************************");
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
System.out.println(gumballMachine);
System.out.println("The current gumball number is:" + gumballMachine.getCount());
System.out.println("****************************************");
}
}