State:状态
角色
Context:环境角色:用于维护 State 实例,这个实例定义当前状态 State:抽象状态角色:聚合到Context环境角色中 ConcreteState :具体的状态角色 ConcreteStateA ConcreteStateB ConcreteStateC
UML类图
案例
案例:抽奖活动项目设计
出现前
package com.javaxl.design.state.before;
import java.util.Random;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2020-02-25 12:57
*/
public class State {
// 当前的状态
private int state;
// 供抽奖的积分
private int score;
// 奖品的数量
private int count;
public State(int score, int count) {
this.score = score;
this.count = count;
}
public int getCount() {
return count;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
// 扣除积分
public void minus() {
// 只有一阶段可以扣积分
this.state = 1;
if (this.state == 1) {
if (this.score >= 50) {
if (this.count == 0) {
System.out.println("奖品领完....");
return;
}
this.score = this.score - 50;
System.out.println("========扣除50积分,当前积分还剩" + this.score + "========");
this.state = 2;
if (luckHit()) {
this.state = 3;
getPrize();
}
} else {
System.out.println("========积分不够,当前积分为" + this.score + "========");
}
}
}
// 十分之一抽中奖品的概率
public boolean luckHit() {
// 只有二阶段可以抽奖
return this.state == 2 ? (new Random().nextInt(10) == 6) : false;
}
public void getPrize() {
if (this.state == 3) {
if (this.count > 0) {
System.out.println("领取奖品....");
this.count = this.count - 1;
} else {
System.out.println("奖品领完....");
}
}
}
}
public class Client {
public static void main(String[] args) {
State state = new State(500,1);
// state.minus();
for (int i = 0; i < 300; i++) {
state.minus();
}
}
}
从上面的编码中,我们可以看出,完成该需求有很多的条件判断,非常不利于后续的维护;上面状态只有4个,代码已经比较复杂了;状态越多,代码嵌套就越复杂,维护成本就越高;
出现后
package com.javaxl.design.state.after;
import java.util.Random;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2020-02-25 15:59
*/
public abstract class State {
// 扣积分
abstract void minus();
// 抽奖
abstract boolean luckHit();
// 获取奖品
abstract void getPrize();
}
class ConcreteStateA extends State{
Context context;
public ConcreteStateA(Context context) {
this.context = context;
}
@Override
void minus() {
if(context.getScore()>=50){
context.setScore(context.getScore()-50);
System.out.println("========扣除50积分,当前积分还剩"+context.getScore()+"========");
context.setState(context.getStateB());
}else{
System.out.println("========积分不够,当前积分为"+context.getScore()+"========");
}
}
@Override
boolean luckHit() {
System.out.println("还在扣费环节,不能抽奖...");
return false;
}
@Override
void getPrize() {
System.out.println("还在扣费环节,不能领取奖品...");
}
}
class ConcreteStateB extends State{
Context context;
public ConcreteStateB(Context context) {
this.context = context;
}
@Override
void minus() {
System.out.println("已经在抽奖环节...");
}
@Override
boolean luckHit() {
boolean flag = new Random().nextInt(10) == 6;
if(flag){
context.setState(context.getStateC());
}else{
context.setState(context.getStateA());
}
return flag;
}
@Override
void getPrize() {
System.out.println("还在抽奖环节,不能领取奖品...");
}
}
class ConcreteStateC extends State{
Context context;
public ConcreteStateC(Context context) {
this.context = context;
}
@Override
void minus() {
System.out.println("已经在领取奖品环节...");
}
@Override
boolean luckHit() {
System.out.println("已经在领取奖品环节...");
return false;
}
@Override
void getPrize() {
if(context.getCount()>0){
System.out.println("领取奖品成功...");
context.setState(context.getStateA());
}else {
System.out.println("活动结束,领取奖品失败...");
context.setState(context.getStateD());
// 不继续抽奖
// System.exit(0);
}
}
}
class ConcreteStateD extends State{
Context context;
public ConcreteStateD(Context context) {
this.context = context;
}
@Override
void minus() {
System.out.println("已经在活动结束,奖品送完环节...");
}
@Override
boolean luckHit() {
System.out.println("已经在活动结束,奖品送完环节...");
return false;
}
@Override
void getPrize() {
System.out.println("已经在活动结束,奖品送完环节...");
}
}
public class Context {
// 当前的状态
private State state;
// 奖品数量
public int count;
// 用户积分
private int score;
// 表示同一个对象的四种状态
private ConcreteStateA stateA = new ConcreteStateA(this);
private ConcreteStateB stateB = new ConcreteStateB(this);
private ConcreteStateC stateC = new ConcreteStateC(this);
private ConcreteStateD stateD = new ConcreteStateD(this);
public Context(int score, int count) {
this.score = score;
this.count = count;
this.state = stateA;
}
// 扣积分
public void minus() {
state.minus();
}
// 抽奖
public void luckHit() {
if (state.luckHit()) {
state.getPrize();
}
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public int getCount() {
return count--;
}
public void setCount(int count) {
this.count = count;
}
public ConcreteStateA getStateA() {
return stateA;
}
public void setStateA(ConcreteStateA stateA) {
this.stateA = stateA;
}
public ConcreteStateB getStateB() {
return stateB;
}
public void setStateB(ConcreteStateB stateB) {
this.stateB = stateB;
}
public ConcreteStateC getStateC() {
return stateC;
}
public void setStateC(ConcreteStateC stateC) {
this.stateC = stateC;
}
public ConcreteStateD getStateD() {
return stateD;
}
public void setStateD(ConcreteStateD stateD) {
this.stateD = stateD;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
public class Client {
public static void main(String[] args) {
// 这次游戏积分500个,用完为止,总奖品数2
Context context = new Context(500,1);
// context.lunkHit();//还在扣费环节,不能抽奖...
for (int i = 0; i < 300; i++) {
context.minus();
context.luckHit();
}
System.out.println("------------------");
}
}
一次没抽中
抽中一次
抽中两次
注意事项和细节
代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中
方便维护。将容易产生问题的 if-else 语句删除了
符合“开闭原则”。容易增删状态
缺点:会产生很多类。每个状态都要一个对应的类,当状态过多时会产生很多类,加大维护难度
应用场景:当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求有不同的行为的时候, 可以考虑使用状态模式
应用
借贷平台状态管理
over......
备案号:湘ICP备19000029号
Copyright © 2018-2019 javaxl晓码阁 版权所有