状态模式(State Pattern) :允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。
Context: 环境类
State: 抽象状态类
ConcreteState: 具体状态类
package 状态模式2;
//环境类 论坛账号类
public class ForumAccount {
private AbstactState state;
private String name;
public ForumAccount(String name) {
this.name = name;
this.state = new PrimaryState(this);
System.out.println(this.name + "注册成功!");
System.out.println("---------------------------------");
}
public AbstactState getState() {
return state;
}
public void setState(AbstactState state) {
this.state = state;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void downloadFile(int score){
state.downloadFile(score);
}
public void writeNode(int score){
state.writeNode(score);
}
public void replyNode(int score){
state.replyNode(score);
}
}
package 状态模式2;
//抽象状态类
public abstract class AbstactState {
protected ForumAccount acc;
protected int point;
protected String stateName;
public abstract void checkState(int score);
public void downloadFile(int score) {
System.out.println(acc.getName() + "下载文件,扣除" + score + "积分。");
this.point -=score;
checkState(score);
System.out.println("剩余积分为:"+ this.point + ",当前级别为:" +
acc.getState().stateName + "。");
}
public void writeNode(int score) {
System.out.println(acc.getName() + "发布留言,增加" + score + "积分。");
this.point +=score;
checkState(score);
System.out.println("剩余积分为:"+ this.point + ",当前级别为:" +
acc.getState().stateName + "。");
}
public void replyNode(int score) {
System.out.println(acc.getName() + "回复留言,增加" + score + "积分。");
this.point +=score;
checkState(score);
System.out.println("剩余积分为:"+ this.point + ",当前级别为:" +
acc.getState().stateName + "。");
}
public int getPoint() {
return point;
}
public void setPoint(int point) {
this.point = point;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
}
package 状态模式2;
//具体状态类 专家状态类
public class HighState extends AbstactState {
public HighState(AbstactState state) {
this.acc = state.acc;
this.point = state.getPoint();
this.setStateName("专家");
}
public void writeNode(int score){
System.out.println(acc.getName() + "发布留言,增加" + score +"*2个积分。");
this.point +=score*2;
checkState(score);
System.out.println("剩余积分为:"+ this.point + ",当前级别为:"+acc.getState().stateName + "。");
}
public void downLoadFile(int score){
System.out.println(acc.getName() + "下载文件,扣除" + score + "/2积分。");
this.point-=score/2;
checkState(score);
System.out.println("剩余积分为:"+this.point + ",当前级别为:" + acc.getState().stateName + "。");
}
@Override
public void checkState(int score) {
if(point<0){
System.out.println("余额不足,文件下载失败!");
this.point+=point;
}else if(point<=100){
acc.setState(new PrimaryState(this));
}else if(point<=1000){
acc.setState(new MiddleState(this));
}
}
}
package 状态模式2;
//具体状态类 高手状态类
public class MiddleState extends AbstactState {
public MiddleState(AbstactState state) {
this.acc = state.acc;
this.point = state.getPoint();
this.setStateName("高手");
}
public void writeNode(int score){
System.out.println(acc.getName() + "发布留言,增加" +
score + "*2个积分。");
this.point +=score*2;
checkState(score);
System.out.println("剩余积分为:"+ this.point + ",当前级别为:" +
acc.getState().getStateName() + "。");
}
@Override
public void checkState(int score) {
if(point>=1000){
acc.setState(new HighState(this));
}else if(point<0){
System.out.println("余额不足,文件下载失败!");
this.point+=score;
} else if(point<=100){
acc.setState(new PrimaryState(this));
}
}
}
package 状态模式2;
//具体状态类 新手状态类
public class PrimaryState extends AbstactState {
public PrimaryState(AbstactState state) {
this.acc = state.acc;
this.point = state.getPoint();
this.setStateName("新手");
}
public PrimaryState(ForumAccount acc){
this.point = 0;
this.acc = acc;
this.setStateName("新手");
}
public void downLoadFile(int score){
System.out.println("对不起,"+acc.getName() + "您没有下载文件的权限。");
}
// public PrimaryState(ForumAccount forumAccount) {
// super(
//
// );
// }
@Override
public void checkState(int score) {
if(point>=1000){
acc.setState(new HighState(this));
}else if(point>=100){
acc.setState(new MiddleState(this));
}
}
}
package 状态模式2;
public class client {
public static void main(String[] args) {
ForumAccount account = new ForumAccount("张三");
account.writeNode(20);
System.out.println("------------------------------------");
account.downloadFile(20);
System.out.println("------------------------------------");
account.replyNode(100);
System.out.println("------------------------------------");
account.writeNode(40);
System.out.println("------------------------------------");
account.downloadFile(80);
System.out.println("------------------------------------");
account.downloadFile(150);
System.out.println("------------------------------------");
account.writeNode(1000);
System.out.println("------------------------------------");
account.downloadFile(80);
System.out.println("------------------------------------");
}
}
package 状态模式;
//银行账户:环境类
public class Account {
private AccountState state;
private String owner;
//构造函数
public Account(String owner, double init){
this.owner =owner;
this.state = new GreenState(init,this);
System.out.println(this.owner +"开户,初始金额为:" +init);
System.out.println("**************************************");
}
public void setState(AccountState state){
this.state =state;
}
//存款
public void deposit(double amount){
System.out.println(this.owner + "存款"+amount + "元");
state.deposit(amount);
System.out.println("现在余额为"+state.balance);
System.out.println("现在账户状态为" + state.getClass().getName());
System.out.println("**************************************");
}
//取款
public void withdraw(double amount){
System.out.println(this.owner +"取款" +amount);
state.withdraw(amount);
System.out.println("现在余额为" +state.balance);
System.out.println("现在账户状态为" + state.getClass().getName());
System.out.println("**************************************");
}
}
package 状态模式;
//抽象状态类
public abstract class AccountState {
protected Account acc;
protected double balance;
//抽象存款方法
public abstract void deposit(double amount) ;
//抽象取款方法
public abstract void withdraw(double amount);
//抽象自我检查状态方法
public abstract void stateCheck();
}
package 状态模式;
//绿色状态 :具体实现类
public class GreenState extends AccountState {
//构造函数
public GreenState(double balance, Account acc) {
this.balance =balance;
this.acc =acc;
}
public GreenState(AccountState state) {
this.balance =state.balance;
this.acc =state.acc;
}
// 计算重新存款后的金额
@Override
public void deposit(double amount) {
this.balance+=amount;
stateCheck();
}
//计算重新取款后的金额
@Override
public void withdraw(double amount) {
this.balance-=amount;
stateCheck();
}
//检查金额是否满足绿色状态,不满足则考虑红色和黄色状态
@Override
public void stateCheck() {
if(balance>=-1000&&balance<0){
acc.setState(new YellowState(this));
}else if(balance<-1000){
acc.setState(new RedState(this));
}
}
}
package 状态模式;
//红色状态:具体实现类
public class RedState extends AccountState {
//构造函数
public RedState(AccountState state) {
this.balance =state.balance;
this.acc =state.acc;
}
// 计算重新存款后的金额
@Override
public void deposit(double amount) {
this.balance+=amount;
stateCheck();
}
// 若前一状态判定为红色状态,则不允许取款,并冻结账户
@Override
public void withdraw(double amount) {
System.out.println("账户被冻结,取款失败。");
}
//判断存款后的金额是否满足红色状态,不满足则考虑黄色和绿色状态
@Override
public void stateCheck() {
if(balance>=0){
acc.setState(new GreenState(this));
}else if(balance>=-1000){
acc.setState(new YellowState(this));
}
}
}
package 状态模式;
//黄色状态:具体实现类
public class YellowState extends AccountState {
//构造函数
public YellowState(AccountState state) {
this.balance =state.balance;
this.acc =state.acc;
}
// 计算重新存款后的金额
@Override
public void deposit(double amount) {
this.balance+=amount;
stateCheck();
}
//计算重新取款后的金额
@Override
public void withdraw(double amount) {
this.balance-=amount;
stateCheck();
}
//检查金额是否满足黄色状态,不满足则考虑红色和绿色状态
@Override
public void stateCheck() {
if(balance>=0){
acc.setState(new GreenState(this));
}else if(balance<-100){
acc.setState(new RedState(this));
}
}
}
package 状态模式;
//客户端测试类
public class client {
public static void main(String[] args) {
Account account = new Account("安娜",19.0);
account.deposit(100);
account.withdraw(200);
account.deposit(1000);
account.withdraw(2000);
account.withdraw(100);
}
}
(1) 状态模式在工作流或游戏等类型的软件中得以广泛使用,甚至可以用于这些系统的核心功能设计,如在政府OA办公系统中,一个批文的状态有多种:尚未办理;正在办理;正在批示;正在审核;已经完成等各种状态,而且批文状态不同时对批文的操作也有所差异。使用状态模式可以描述工作流对象(如批文)的状态转换以及不同状态下它所具有的行为。
(2) 在目前主流的RPG(Role Play Game,角色扮演游戏)中,使用状态模式可以对游戏角色进行控制,游戏角色的升级伴随着其状态的变化和行为的变化。对于游戏程序本身也可以通过状态模式进行总控,一个游戏活动包括开始、运行、结束等状态,通过对状态的控制可以控制系统的行为,决定游戏的各个方面,因此可以使用状态模式对整个游戏的架构进行设计与实现。
状态模式允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象,状态模式是一种对象行为型模式。
状态模式包含三个角色:环境类又称为上下文类,它是拥有状态的对象,在环境类中维护一个抽象状态类State的实例,这个实例定义当前状态,在具体实现时,它是一个State子类的对象,可以定义初始状态;抽象状态类用于定义一个接口以封装与环境类的一个特定状态相关的行为;具体状态类是抽象状态类的子类,每一个子类实现一个与环境类的一个状态相关的行为,每一个具体状态类对应环境的一个具体状态,不同的具体状态类其行为有所不同。
状态模式描述了对象状态的变化以及对象如何在每一种状态下表现出不同的行为。
状态模式的主要优点在于封装了转换规则,并枚举可能的状态,它将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为,还可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数;其缺点在于使用状态模式会增加系统类和对象的个数,且状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,对于可以切换状态的状态模式不满足“开闭原则”的要求。
状态模式适用情况包括:对象的行为依赖于它的状态(属性)并且可以根据它的状态改变而改变它的相关行为;代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,使客户类与类库之间的耦合增强。