23种设计模式(14):状态模式

来源:互联网 发布:密室逃脱窃取数据攻略 编辑:程序博客网 时间:2024/06/03 21:59

资料摘自《Head First设计模式》

状态模式--允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
示例:万能糖果公司想制造出糖果机,该糖果机的工作状态如下

上面所示,糖果机的状态有:没有25分钱、有25分钱、售出糖果、糖果售罄
下面来实现这个糖果机:
public class GumballMachine {
final static int SOLD_OUT = 0; //糖果售罄状态
final static int NO_QUARTER = 1; //没有25分钱状态
final static int HAS_QUARTER = 2; //有25分钱状态
final static int SOLD = 3; //售出糖果状态
int state = SOLD_OUT; //当前状态
int count = 0; //糖果数目
public GumballMachine(int numberGumballs){ 
this.count = numberGumballs;
if(numberGumballs>0){
this.state = NO_QUARTER; 
}
}
//投币
public void insertQuarter(){
if(state == HAS_QUARTER){
System.out.println("You can't insert another quarter");
}else if(state == NO_QUARTER){
state = HAS_QUARTER;
System.out.println("You insert a quarter");
}else if(state == SOLD_OUT){
System.out.println("You can't insert a quarter, the machine is sold out");
}else if(state == SOLD){
System.out.println("Please wait, we're already giving you a gumball");
}
}
//退币
public void ejectQuarter(){
if(state == HAS_QUARTER){
System.out.println("Quarter returned");
}else if(state == NO_QUARTER){
state = HAS_QUARTER;
System.out.println("You haven't inserted a quarter");
}else if(state == SOLD){
//如果顾客已经转动曲柄,就不能再退钱了,他已经拿到糖果了
System.out.println("Sorry, you already turned the crank");
}else if(state == SOLD_OUT){
//如果糖果售罄,就不可能接受25分钱,当然也不可能退钱
System.out.println("You can't eject, you haven't inserted a quarter yet");
}
}
//转动曲柄
public void turnCrank(){
if(state == SOLD){
System.out.println("Turning twice doesn't get you another gumball!");
}else if(state == NO_QUARTER){
System.out.println("You turned but there's no quarter");
}else if(state == SOLD_OUT){
System.out.println("You turned, but there are no gumballs");
}else if(state == HAS_QUARTER){
System.out.println("You turned...");
state = SOLD;
dispense();
}
}
//发放糖果
public void dispense(){
if(state == SOLD){
System.out.println("A gumball comes rolling out the solt");
count = count - 1;
if(count == 0){
System.out.println("Oops, out of gumballs!");
state = SOLD_OUT;
}else{
state = NO_QUARTER;
}
}else if(state == NO_QUARTER){
//不该发生
System.out.println("You need to pay first");
}else if(state == SOLD_OUT){
//不该发生
System.out.println("No gumball dispensed");
}else if(state == HAS_QUARTER){
//不该发生
System.out.println("No gumball dispensed");
}
}
}
万能糖果公司已经将你的代码放进他们的新机器中,然后让他们的质保专家进行测试。到目前为止,一切都很顺利。但是,现在他们想要变点花样:当曲柄被转动时,有10%的机率掉下来的是两颗糖果(多送你一个)
根据上面的代码进行修改:
首先,你必须加上一个新的状态
然后,你必须在每个方法中加入一个新的条件判断处理该状态(照这个说法,增加的状态越多,到时进行的修改越多,越乱)
解决方案:使用状态模式
首先,定义一个State接口。在这个接口内,糖果机的每个动作都有一个对应的方法
public interface State {
public void insertQuarter();
public void ejectQuarter();
public void turnCrank();
public void dispense();
}
然后为机器中的每个状态实现状态类。这些状态类将负责在对应的状态下进行机器的行为
public class NoQuarterState implements State {
GumballMachine gumballMachine;


public NoQuarterState(GumballMachine gumballMachine){
this.gumballMachine = gumballMachine;
}


@Override
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("You inserted a quarter");
this.gumballMachine.setState(this.gumballMachine.getHasQuarterState());
}


@Override
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("You haven't inserted a quarter");
}


@Override
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("You turned, but there's no quarter");
}


@Override
public void dispense() {
// TODO Auto-generated method stub
System.out.println("You need to pay first");
}
}
public class HasQuarterState implements State {


GumballMachine gumballMachine;

public HasQuarterState(GumballMachine gumballMachine){
this.gumballMachine = gumballMachine;
}

@Override
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("You can't insert another quarter");
}


@Override
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("Quarter returned");
gumballMachine.setState(gumballMachine.getNoQuarterState());
}


@Override
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("You turned...");
gumballMachine.setState(gumballMachine.getSoldState());
}


@Override
public void dispense() {
// TODO Auto-generated method stub
System.out.println("No gumball dispensed");
}
}
public class SoldState implements State {


GumballMachine gumballMachine;

public SoldState(GumballMachine gumballMachine){
this.gumballMachine = gumballMachine;
}

@Override
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("Please wait, we're already giving you a gumball");
}


@Override
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("Sorry, you already turned the crank");
}


@Override
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("Turning twice doesn't get you another gumball!");
}


@Override
public void dispense() {
// TODO Auto-generated method stub
gumballMachine.releaseBall();
if(gumballMachine.getCount() > 0){
gumballMachine.setState(gumballMachine.getNoQuarterState());
}else{
System.out.println("Oops, out of gumballs!");
gumballMachine.setState(gumballMachine.getSoldOutState());
}
}
}

public class SoldOutState implements State {


GumballMachine gumballMachine;

public SoldOutState(GumballMachine gumballMachine){
this.gumballMachine = gumballMachine;
}

@Override
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("You can't insert a quarter, the machine is sold out");
}


@Override
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("You can't eject, you haven't inserted a quarter yet");
}


@Override
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("You turned, but there are no qumballls");
}


@Override
public void dispense() {
// TODO Auto-generated method stub
System.out.println("No gumball dispense");
}
}
最后,我们要摆脱旧的条件代码,取而代之的方式是,将动作委托到状态类
public class GumballMachine {
State soldOutState; 
State noQuarterState;
State hasQuarterState;
State soldState;
State state = soldOutState;
int count = 0;
public GumballMachine(int numberGumballs){
//每一种状态都创建一个状态实例
this.soldOutState = new SoldOutState(this); 
this.noQuarterState = new NoQuarterState(this); 
this.hasQuarterState = new HasQuarterState(this); 
this.soldState = new SoldState(this); 
this.count = numberGumballs;
if(numberGumballs>0){
this.state = this.noQuarterState; 
}
}
//投币
public void insertQuarter(){
this.state.insertQuarter();
}
//退币
public void ejectQuarter(){
this.state.ejectQuarter();
}
//转动曲柄
public void turnCrank(){
this.state.turnCrank();
this.state.dispense();
}
//释放糖果
public void releaseBall(){
System.out.println("A gumball comes rolling out the slot...");
if(this.count != 0){
this.count = this.count - 1;
}
}
public void setState(State state){
this.state = state;
}
//这里还有其它的方法
public State getHasQuarterState(){
return this.hasQuarterState;
}
public State getNoQuarterState(){
return this.noQuarterState;
}
public State getSoldState(){
return this.soldState;
}
public State getSoldOutState(){
return this.soldOutState;
}
}

0 0
原创粉丝点击