状态模式(形式一)
程序员文章站
2022-06-17 17:10:26
...
定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
例子:糖果机,有多种状态以及多种行为,每种状态执行每种行为会得到不同的结果,并转向下一个不同的状态。
使用原始的方法:在糖果机里面定义对应的状态(属性)以及行为(方法),然后在方法执行的时候,用if...else...判断当前状态,然后执行不同的逻辑代码。
弊端:不易于扩展,当添加新的状态以及行为时,需要在糖果机里面新增属性以及方法,还要修改之前方法里的代码。
talk is cheap show me the code
首先定义状态接口,包含所有的行为
public interface State {
// 投入25分钱
void insertQuarter();
// 退回25分钱
void ejectQuarter();
// 转动曲柄
void turnCrank();
// 发放糖果
void dispense();
}
然后定义一个抽象类,实现状态接口,并提供糖果机的引用以及所有方法的默认实现
public abstract class AbstractState implements State {
protected GumballMachine gumballMachine;
public AbstractState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
throw new UnsupportedOperationException();
}
@Override
public void ejectQuarter() {
throw new UnsupportedOperationException();
}
@Override
public void turnCrank() {
throw new UnsupportedOperationException();
}
@Override
public void dispense() {
throw new UnsupportedOperationException();
}
}
接下来写所有的状态实现类
/**
* 没有25分钱
* @author z_hh
* @time 2018年7月22日
*/
public class NoQuarterState extends AbstractState {
public NoQuarterState(GumballMachine gumballMachine) {
super(gumballMachine);
}
@Override
public void insertQuarter() {
System.out.println("You insert a quarter");
gumballMachine.setState(gumballMachine.getHasQuarterState());
}
@Override
public void ejectQuarter() {
System.out.println("You haven't inserted a quarter");
}
@Override
public void turnCrank() {
System.err.println("You turned, but there's no quarter");
}
@Override
public void dispense() {
System.out.println("You need to pay first");
}
}
/**
* 有25分钱
* @author z_hh
* @time 2018年7月22日
*/
public class HasQuarterState extends AbstractState {
public HasQuarterState(GumballMachine gumballMachine) {
super(gumballMachine);
}
@Override
public void insertQuarter() {
System.out.println("You can't insert another quarter");
}
@Override
public void ejectQuarter() {
System.out.println("Quarter returned");
gumballMachine.setState(gumballMachine.getNoQuarterState());
}
@Override
public void turnCrank() {
System.out.println("You turned...");
gumballMachine.setState(gumballMachine.getSoldState());
}
@Override
public void dispense() {
System.out.println("No gumball dispensed");
}
}
/**
* 售出糖果
* @author z_hh
* @time 2018年7月22日
*/
public class SoldState extends AbstractState {
public SoldState(GumballMachine gumballMachine) {
super(gumballMachine);
}
@Override
public void insertQuarter() {
System.out.println("Please wait, we're already giving you a gumball");
}
@Override
public void ejectQuarter() {
System.out.println("Sorry, you already turned the crank");
}
@Override
public void turnCrank() {
System.out.println("Turning twice doesn't get you another gumball");
}
@Override
public void dispense() {
gumballMachine.releaseBall();
if (gumballMachine.getCount() > 0) {
gumballMachine.setState(gumballMachine.getNoQuarterState());
} else {
System.out.println("Oops, out of gumballs");
gumballMachine.setState(gumballMachine.getSoldOutState());
}
}
}
/**
* 糖果售罄
* @author z_hh
* @time 2018年7月22日
*/
public class SoldOutState extends AbstractState {
public SoldOutState(GumballMachine gumballMachine) {
super(gumballMachine);
}
@Override
public void insertQuarter() {
System.out.println("You can't insert a quarter, the machine is sole out");
}
@Override
public void ejectQuarter() {
System.out.println("You can't eject, you haven't inserted a quarter yet");
}
@Override
public void turnCrank() {
System.out.println("You turned, but there are no gumballs");
}
@Override
public void dispense() {
System.out.println("No gumball dispensed");
}
}
最后写糖果机的代码
public class GumballMachine {
private State soldOutState;
private State noQuarterState;
private State hasQuarterState;
private State soldState;
private State state = soldOutState;
private int count = 0;
public GumballMachine(int numberGumball) {
soldOutState = new SoldOutState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);
this.count = numberGumball;
if (count > 0) {
state = noQuarterState;
}
}
public void insertQuarter() {
state.insertQuarter();
}
public void ejectQuarter() {
state.ejectQuarter();
}
public void turnCrank() {
state.turnCrank();
state.dispense();
}
void setState(State state) {
this.state = state;
}
void releaseBall() {
System.out.println("A gumball comes rolling out the slot...");
if (count != 0) {
count--;
}
}
public State getState() {
return state;
}
public State getSoldOutState() {
return soldOutState;
}
public State getNoQuarterState() {
return noQuarterState;
}
public State getHasQuarterState() {
return hasQuarterState;
}
public State getSoldState() {
return soldState;
}
public int getCount() {
return count;
}
@Override
public String toString() {
return "GumballMachine [state=" + state.getClass().getSimpleName() + ", count=" + count + "]";
}
}
测试:
public class Test {
public static void main(String[] args) {
// 创建糖果机,初始化5颗糖
GumballMachine gumballMachine = new GumballMachine(5);
System.out.println(gumballMachine);
gumballMachine.insertQuarter();// 投入25分钱
gumballMachine.turnCrank();// 转动曲柄
System.out.println(gumballMachine);
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
System.out.println(gumballMachine);
}
}
结果:
GumballMachine [state=NoQuarterState, count=5]
You insert a quarter
You turned...
A gumball comes rolling out the slot...
GumballMachine [state=NoQuarterState, count=4]
You insert a quarter
You turned...
A gumball comes rolling out the slot...
You insert a quarter
You turned...
A gumball comes rolling out the slot...
GumballMachine [state=NoQuarterState, count=2]
注意:本文案例来自《Head First设计模式》。
问题1:如果新增了状态以及行为,除了这种方案------接口增加方法,所有实现类也对应添加并且实现,新增状态实现类,糖果机增加该类的引用,然后修改每个状态实现类的相关代码。还有其它方法吗?
问题2:除了在糖果机类声明所有状态的引用,以及构造函数赋值,还有其它的方法吗?
上一篇: RHEL6上课笔记之acl
下一篇: 剑指offer 16 数值的整数次方