设计模式之状态模式
- 状态模式相关总结
- 糖果机案例
状态模式相关总结
- 在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。
- 通常命令模式的接口中只有一个方法。而状态模式的接口中有一个或者多个方法。而且,状态模式的实现类的方法,一般返回值,或者是改变实例变量的值。也就是说,状态模式一般和对象的状态有关。实现类的方法有不同的功能,覆盖接口中的方法。状态模式和命令模式一样,也可以用于消除 if…else 等条件选择语句。
- 优点: 1、封装了转换规则。 2、枚举可能的状态,在枚举状态之前需要确定状态种类。 3**、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。** 4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。 5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
糖果机案例
普通设计方案
一个糖果机类,一个测试类
package state.bad;
/**
* 糖果机
*/
public class CandyMachine {
final static int SOLD_OUT = 0; //卖光了
final static int OnReady = 1; //有糖果,在等待状态
final static int HasCoin = 2; //有硬币
final static int SOLDING = 3; //正在售出 正在转动曲柄
int state = SOLD_OUT; //机器目前处于什么状态
int count = 0;
public CandyMachine(int count) {
this.count = count;
if (count > 0) {
state = OnReady;
}
}
//空了,重新加入糖果
public void refill(int numGumBalls) {
this.count = numGumBalls;
state = OnReady;
}
//放入硬币
public void insertCoin() {
if (state == HasCoin) {
System.out.println("已经有硬币了,不能插!");
} else if (state == OnReady) {
state = HasCoin;
System.out.println("你插入了一个硬币!");
} else if (state == SOLD_OUT) {
System.out.println("你不能插硬币,已经卖光了!");
} else if (state == SOLDING) {
System.out.println("请等一下,我们正在给你!");
}
}
//用户后悔,退还硬币(但是你必须还没有转动把柄)
public void returnCoin() {
if (state == HasCoin) {
System.out.println("诺,硬币还给你!");
state = OnReady;
} else if (state == OnReady) {
System.out.println("你还没有插入硬币!");
} else if (state == SOLDING) {
System.out.println("对不起,把柄已经在转动,我们正要把糖果给你了!");
} else if (state == SOLD_OUT) {
System.out.println("糖果已经卖光了!");
}
}
//转动把柄
public void turnCrank(){
if (state == SOLDING) {
System.out.println("你转两次也不会给你更多的糖果!");
} else if (state == OnReady) {
System.out.println("还是在待机状态,你还没有放入硬币!");
} else if (state == SOLD_OUT) {
System.out.println("你转了把柄,但是已经没有糖果了!");
} else if (state == HasCoin) {
System.out.println("你转动了!");
state = SOLDING;
dispense();
}
}
//糖果机的分发糖果的
private void dispense() {
if(state == SOLDING){
System.out.println("一个糖果正在从硬币槽中掉下!");
count--;
if(count == 0){
System.out.println("Oops!,糖果卖光了!");
state = SOLD_OUT;
}else {
state = OnReady;
}
}else if (state == OnReady) {
System.out.println("你应该先支付一个硬币!");
} else if (state == SOLD_OUT) {
System.out.println("没有糖果分发!");
} else if (state == HasCoin) {
System.out.println("没有糖果分发!");
}
}
//打印当前状态
public void printState(){
if(state == 0){
System.out.println("-----------SOLD_OUT--------");
}else if(state == 1){
System.out.println("-----------OnReady---------");
}else if(state == 2){
System.out.println("-----------HasCoin---------");
}else {
System.out.println("------------SOLDING--------");
}
}
}
测试类:
package state.bad;
public class MyTest {
public static void main(String[] args) {
CandyMachine candyMachine = new CandyMachine(5);
candyMachine.printState();
candyMachine.insertCoin();
candyMachine.turnCrank();
candyMachine.printState();
candyMachine.insertCoin();
candyMachine.returnCoin();
candyMachine.turnCrank();
candyMachine.printState();
candyMachine.insertCoin();
candyMachine.turnCrank();
candyMachine.insertCoin();
candyMachine.turnCrank();
candyMachine.returnCoin();
candyMachine.printState();
candyMachine.insertCoin();
candyMachine.insertCoin();
candyMachine.turnCrank();
candyMachine.insertCoin();
candyMachine.turnCrank();
candyMachine.insertCoin();
candyMachine.turnCrank();
candyMachine.printState();
}
}
输出:
新需求:
状态模式设计
各种状态的接口:
package state.good;
/**
* 面向接口编程
* 状态接口
*/
public interface State {
public void insertCoin();
public void returnCoin();
public void turnCrank();
public void dispense();
public void refill();
public void printState();
}
package state.good;
/**
* 糖果机
*/
public class CandyMachine {
private State mSoldOutState;
private State mOnReadyState;
private State mHasCoinState;
private State mSoldingState;
private State mWinnerState; //中奖了 给您两个糖果
private State state;
private int count;
public CandyMachine(int count) {
this.count = count;
mSoldOutState = new SoldOutState(this); //传入当前类的对象
mOnReadyState = new OnReadyState(this);
mHasCoinState = new HasCoinState(this);
mSoldingState = new SoldingState(this);
mWinnerState = new WinnerState(this);
if(count > 0){
state = mOnReadyState;
}else {
state = mSoldOutState;
}
}
//设置当前的状态
public void setState(State state){
this.state = state;
}
//空了,重新加入糖果
public void refill(int numGumBalls) {
state.refill();
}
//放入硬币
public void insertCoin() {
state.insertCoin();
}
//用户后悔,退还硬币(但是你必须还没有转动把柄)
public void returnCoin() {
state.returnCoin();
}
//转动把柄
public void turnCrank(){
state.turnCrank(); //转动之后
state.dispense(); //内部分发糖果
}
//糖果机的分发糖果的
private void dispense() {
state.dispense();
}
//打印当前状态
public void printState(){
state.printState();
}
public void releaseCandy() {
System.out.println("一个糖果正在从槽里面掉下来!");
if (count != 0) {
count = count - 1;
}
}
//相关get属性
public State getmSoldOutState() {
return mSoldOutState;
}
public State getmOnReadyState() {
return mOnReadyState;
}
public State getmHasCoinState() {
return mHasCoinState;
}
public State getmSoldingState() {
return mSoldingState;
}
public State getmWinnerState() {
return mWinnerState;
}
public int getCount(){
return count;
}
}
package state.good;
import java.util.Random;
/**
* 有硬币状态
*/
public class HasCoinState implements State {
private CandyMachine candyMachine;
public HasCoinState(CandyMachine candyMachine) {
this.candyMachine = candyMachine;
}
@Override
public void insertCoin() {
System.out.println("已经有硬币了,不能插!");
}
@Override
public void returnCoin() {
System.out.println("诺,硬币还给你!");
candyMachine.setState(candyMachine.getmOnReadyState());
}
@Override
public void turnCrank() {
System.out.println("你转动了!");
Random ranWinner = new Random();
int winner = ranWinner.nextInt(10); //生成一个
if(winner == 0){ //1/10概率
candyMachine.setState(candyMachine.getmWinnerState()); //赢家状态
}else {
candyMachine.setState(candyMachine.getmSoldingState()); //正常状态
}
}
@Override
public void dispense() {
}
@Override
public void refill() {
}
@Override
public void printState() {
System.out.println("---------HasCoinState--------");
}
}
package state.good;
public class OnReadyState implements State{
private CandyMachine candyMachine;
public OnReadyState(CandyMachine candyMachine) {
this.candyMachine = candyMachine;
}
@Override
public void insertCoin() {
System.out.println("你插入了一个硬币!");
candyMachine.setState(candyMachine.getmHasCoinState());
}
@Override
public void returnCoin() {
System.out.println("你还没有插入硬币!");
}
@Override
public void turnCrank() {
System.out.println("还是在待机状态,你还没有放入硬币!");
}
//待机状态下不放糖果 不实现
@Override
public void dispense() {
}
@Override
public void refill() {
}
@Override
public void printState() {
System.out.println("--------OnReadyState---------");
}
}
package state.good;
public class SoldingState implements State{
private CandyMachine candyMachine;
public SoldingState(CandyMachine candyMachine) {
this.candyMachine = candyMachine;
}
@Override
public void insertCoin() {
System.out.println("请等一下,我们正在给你!");
}
@Override
public void returnCoin() {
System.out.println("对不起,把柄已经在转动,我们正要把糖果给你了!");
}
@Override
public void turnCrank() {
System.out.println("你转两次也不会给你更多的糖果!");
}
@Override
public void dispense() {
candyMachine.releaseCandy();
if(candyMachine.getCount() > 0){
candyMachine.setState(candyMachine.getmOnReadyState());
}else {
System.out.println("Oops!,糖果卖光了!");
candyMachine.setState(candyMachine.getmSoldOutState());
}
}
@Override
public void refill() {
}
@Override
public void printState() {
System.out.println("--------SoldingState-----");
}
}
package state.good;
public class SoldOutState implements State {
private CandyMachine candyMachine;
public SoldOutState(CandyMachine candyMachine) {
this.candyMachine = candyMachine;
}
@Override
public void insertCoin() {
System.out.println("你不能插硬币,已经卖光了!");
}
@Override
public void returnCoin() {
System.out.println("糖果已经卖光了!");
}
@Override
public void turnCrank() {
System.out.println("你转了把柄,但是已经没有糖果了!");
}
@Override
public void dispense() {
}
@Override
public void refill() {
}
@Override
public void printState() {
System.out.println("---------SoldOutState----------");
}
}
赢家的状态:
package state.good;
public class WinnerState implements State {
private CandyMachine candyMachine;
public WinnerState(CandyMachine candyMachine) {
this.candyMachine = candyMachine;
}
@Override
public void insertCoin() {
System.out.println("请等一下,我们正在给你!");
}
@Override
public void returnCoin() {
System.out.println("对不起,把柄已经在转动,我们正要把糖果给你了!");
}
@Override
public void turnCrank() {
System.out.println("你转两次也不会给你更多的糖果!");
}
@Override
public void dispense() {
candyMachine.releaseCandy();
if(candyMachine.getCount() == 0){ //只有一个糖果
candyMachine.setState(candyMachine.getmSoldOutState());
}else {
System.out.println("你中大奖了!给你两颗糖果!");
candyMachine.releaseCandy();
if(candyMachine.getCount() > 0){
candyMachine.setState(candyMachine.getmOnReadyState());
}else {
candyMachine.setState(candyMachine.getmSoldOutState());
}
}
}
@Override
public void refill() {
}
@Override
public void printState() {
System.out.println("--------WinnerState------------");
}
}
测试类:和方案一完全一样 。
输出效果完全一样: