状态模式
基本介绍
- 状态模式( State Pattern ):它主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。状态和行为是一一对应的,状态之间可以相互转换
- 当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类
- 类图:
- Context 类为环境角色 , 用于维护 State 实例这个实例定义当前状态
- State 是抽象状态角色定义一个接口封装与 Context 的一个特点接口相关行为
- ConcreteState 具体的状态角色,每个子类实现一个与 Context 的一个状态相关行为
应用举例
-
用一个应用来举例:
-
类图:
-
代码实现:
public abstract class State {public abstract void deductMoney();public abstract boolean raffle();public abstract void dispensePrize();}
public class NoRaffleState extends State {RaffleActivity activity;public NoRaffleState(RaffleActivity activity) {this.activity = activity;}@Overridepublic void deductMoney() {System.out.println("扣除50积分成功,您可以抽奖了");activity.setState(activity.getCanRaffleState());}@Overridepublic boolean raffle() {System.out.println("扣了积分才能抽奖喔!");return false;}@Overridepublic void dispensePrize() {System.out.println("不能发放奖品");}
}
public class CanRaffleState extends State {RaffleActivity activity;public CanRaffleState(RaffleActivity activity) {this.activity = activity;}@Overridepublic void deductMoney() {System.out.println("已经扣取过了积分");}@Overridepublic boolean raffle() {System.out.println("正在抽奖,请稍等!");Random r = new Random();int num = r.nextInt(10);if(num == 0){activity.setState(activity.getDispenseState());return true;}else{System.out.println("很遗憾没有抽中奖品!");activity.setState(activity.getNoRafflleState());return false;}}@Overridepublic void dispensePrize() {System.out.println("没中奖,不能发放奖品");}
}
public class DispenseState extends State {RaffleActivity activity;public DispenseState(RaffleActivity activity) {this.activity = activity;}@Overridepublic void deductMoney() {System.out.println("不能扣除积分");}@Overridepublic boolean raffle() {System.out.println("不能抽奖");return false;}@Overridepublic void dispensePrize() {if(activity.getCount() > 0){System.out.println("恭喜中奖了");activity.setState(activity.getNoRafflleState());}else{System.out.println("很遗憾,奖品发送完了");activity.setState(activity.getDispensOutState());}}
}
public class DispenseOutState extends State {RaffleActivity activity;public DispenseOutState(RaffleActivity activity) {this.activity = activity;}@Overridepublic void deductMoney() {System.out.println("奖品发送完了,请下次再参加");}@Overridepublic boolean raffle() {System.out.println("奖品发送完了,请下次再参加");return false;}@Overridepublic void dispensePrize() {System.out.println("奖品发送完了,请下次再参加");}
}
public class RaffleActivity {State state = null;int count = 0;State noRafflleState = new NoRaffleState(this);State canRaffleState = new CanRaffleState(this);State dispenseState = new DispenseState(this);State dispensOutState = new DispenseOutState(this);public RaffleActivity( int count) {this.state = getNoRafflleState();this.count = count;}public void debuctMoney(){state.deductMoney();}public void raffle(){if(state.raffle()){state.dispensePrize();}}public State getState() {return state;}public void setState(State state) {this.state = state;}public int getCount() {int curCount = count; count--;return curCount;}public void setCount(int count) {this.count = count;}public State getNoRafflleState() {return noRafflleState;}public void setNoRafflleState(State noRafflleState) {this.noRafflleState = noRafflleState;}public State getCanRaffleState() {return canRaffleState;}public void setCanRaffleState(State canRaffleState) {this.canRaffleState = canRaffleState;}public State getDispenseState() {return dispenseState;}public void setDispenseState(State dispenseState) {this.dispenseState = dispenseState;}public State getDispensOutState() {return dispensOutState;}public void setDispensOutState(State dispensOutState) {this.dispensOutState = dispensOutState;}
}
public class ClientTest {public static void main(String[] args) {RaffleActivity activity &#61; new RaffleActivity(1);for (int i &#61; 0; i < 30; i&#43;&#43;) {System.out.println("--------第" &#43; (i &#43; 1) &#43; "次抽奖----------");activity.debuctMoney();activity.raffle();}}}
- 结果&#xff1a;
总结
- 代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中。
- 方便维护&#xff1a;将容易产生问题的 if else 语句删除了&#xff0c;如果把每个状态的行为都放到一个类中&#xff0c;每次调用方法时都要判断当前是什么状态&#xff0c;不但会产出很多 if else 语句&#xff0c;而且容易出错。
- 符合“开闭原则”。容易增删状态。
- 会产生很多类。每个状态都要一个对应的类&#xff0c;当状态过多时会产生很多类&#xff0c;加大维护难度。
应用场景&#xff1a;当一个事件或者对象有很多种状态&#xff0c;状态之间会相互转换&#xff0c;对不同的状态要求有不同的行为的时候&#xff0c;可以考虑使用状态模式。