本文是阅读《Head First 设计模式》的学习记录。详细内容可以自行阅读书本
状态模式
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
举例
一家糖果公司需要实现一个糖果售货机,它的实现逻辑如下,需要先投入1元,再转动曲柄,机器人吐出糖果,如果还有剩余糖果就继续售货:
如果我们通过条件语句来控制,也可以实现代码逻辑,但是代码会很难扩展,所以需要使用状态模式来实现。
1.定义状态接口,将影响状态的行为封装到里面。并且所有的状态都必须实现它。
public interface State {
/**
* 投钱
*/
void insertMoney();
/**
* 退钱
*/
void ejectMoney();
/**
* 转动曲柄
*/
void turnCrank();
/**
* 出糖果
*/
void dispense();
String description();
}
2.实现上图四个状态
public class NoMoneyState implements State{
GumballMachine gumballMachine;
public NoMoneyState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertMoney() {
System.out.println("inserted money");
gumballMachine.setState(gumballMachine.getHasMoneyState());
}
@Override
public void ejectMoney() {
System.out.println("ignore !");
}
@Override
public void turnCrank() {
System.out.println("ignore !");
}
@Override
public void dispense() {
System.out.println("ignore !");
}
@Override
public String description() {
return "NoMoneyState";
}
}
public class HasMoneyState implements State{
GumballMachine gumballMachine;
public HasMoneyState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertMoney() {
System.out.println("ignore !");
}
@Override
public void ejectMoney() {
System.out.println("money return ");
gumballMachine.setState(gumballMachine.getNoMoneyState());
}
@Override
public void turnCrank() {
System.out.println("turned... ");
gumballMachine.setState(gumballMachine.getSoldState());
}
@Override
public void dispense() {
System.out.println("ignore !");
}
@Override
public String description() {
return "HasMoneyState";
}
}
public class SoldState implements State{
GumballMachine gumballMachine;
public SoldState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertMoney() {
System.out.println("ignore !");
}
@Override
public void ejectMoney() {
System.out.println("ignore !");
}
@Override
public void turnCrank() {
System.out.println("ignore !");
}
@Override
public void dispense() {
System.out.println("dispense");
gumballMachine.releaseBall();
gumballMachine.setState(gumballMachine.getCount() > 0 ? gumballMachine.getNoMoneyState() :
gumballMachine.getSoldOutState());
}
@Override
public String description() {
return "SoldState";
}
}
public class SoldOutState implements State{
// 糖果售空,该状态下不处理任何行为
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertMoney() {
System.out.println("ignore !");
}
@Override
public void ejectMoney() {
System.out.println("ignore !");
}
@Override
public void turnCrank() {
System.out.println("ignore !");
}
@Override
public void dispense() {
System.out.println("ignore !");
}
@Override
public String description() {
return "SoldOutState";
}
}
3.实现售货机类
public class GumballMachine {
State hasMoneyState, noMoneyState, soldOutState, soldState;
State state;
int count = 0;
public GumballMachine(int count) {
this.count = count;
hasMoneyState = new HasMoneyState(this);
noMoneyState = new NoMoneyState(this);
soldOutState = new SoldOutState(this);
soldState = new SoldState(this);
state = count > 0 ? noMoneyState : soldOutState;
}
public void insertMoney() {
state.insertMoney();
}
public void ejectMoney() {
state.ejectMoney();
}
public void turnCrank() {
state.turnCrank();
}
public void dispense() {
state.dispense();
}
public void setState(State state) {
System.out.println(this.state.description() + " -> " + state.description());
this.state = state;
}
public int getCount() {
return count;
}
/**
* 出糖果方法
*/
void releaseBall() {
System.out.println("a gumball comes rolling out the slot ...");
if (count != 0) {
count--;
}
}
public State getHasMoneyState() {
return hasMoneyState;
}
public State getNoMoneyState() {
return noMoneyState;
}
public State getSoldOutState() {
return soldOutState;
}
public State getSoldState() {
return soldState;
}
}
4.测试
public static void main(String[] args) {
GumballMachine gumballMachine = new GumballMachine(1);
for (int i = 0; i <= 1; i++){
System.out.println(" test " + i);
gumballMachine.insertMoney();
gumballMachine.turnCrank();
gumballMachine.dispense();
}
}