1.状态模式 在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的 (stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。
在UML中可以使用状态图来描述对象状态的变化。

状态模式(State Pattern) :允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。
状态模式包含如下角色: - Context: 环境类 - State: 抽象状态类 - ConcreteState: 具体状态类
2.实例
在某论坛系统中,用户可以发表留言,发表留言将增加积分;用户也可以回复留言,回复留言也将增加积分;用户还可以下载文件,下载文件将扣除积分。该系统用户分为三个等级,分别是新手、高手和专家,这三个等级对应三种不同的状态,这三种状态分别定义如下:

项目结构图如下:

定义论坛积分类
public class ForumAccount {
private AbstractState 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 AbstractState getState() {
return state;
}
public void setState(AbstractState 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 writeNote(int score){
state.writeNote(score);
}
public void replyNote(int score){
state.replyNote(score);
}
}
定义论坛状态抽象类
public abstract class AbstractState {
protected ForumAccount forumAccount;
protected int point;
protected String stateName;
public abstract void checkState(int score);
public void downLoadFile(int score) {
System.out.println(forumAccount.getName()+"下载文件,扣除"+score+"积分!");
this.point-=score;
this.checkState(score);
System.out.println("剩余积分为:"+this.point+",当前级别 为:"+forumAccount.getState().stateName+".");
}
public void writeNote(int score) {
System.out.println(forumAccount.getName()+"发布留言,增加"+score+"积分。");
this.point+=score;
this.checkState(score);
System.out.println("剩余积分为:"+this.point+",当前级别为:"+forumAccount.getState().stateName+".");
}
public void replyNote(int score) {
System.out.println(forumAccount.getName()+"回复留言,增加"+score+"积分。");
this.point+=score;
this.checkState(score);
System.out.println("剩余积分为:"+this.point+",当前级别为:"+forumAccount.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;
}
}
初级会员类
public class PrimaryState extends AbstractState {
public PrimaryState(AbstractState state) {
this.forumAccount=state.forumAccount;
this.point=state.getPoint();
this.stateName="新手";
}
public PrimaryState(ForumAccount forumAccount) {
this.point=0;
this.forumAccount=forumAccount;
this.stateName="新手";
}
public void downLoadFile(int score){
System.out.println("对不起,"+forumAccount.getName()+"您没有下载文件的权限!");
}
@Override
public void checkState(int score) {
if(this.point>=1000){
forumAccount.setState(new HightState(this));
}else if(this.point>=100){
forumAccount.setState(new MiddleState(this));
}
}
}
中级会员类
public class MiddleState extends AbstractState {
public MiddleState(AbstractState state) {
this.forumAccount=state.forumAccount;
this.point=state.getPoint();
this.stateName="高手";
}
public void writeNote(int score){
System.out.println(forumAccount.getName()+"发布留言,增加"+score+"*2个积分");
this.point+=score*2;
this.checkState(score);
System.out.println("剩余积分为:"+this.point+",当前级别为:"+forumAccount.getState().stateName+".");
}
@Override
public void checkState(int score) {
if(point>=1000){
forumAccount.setState(new HightState(this));
}else if(this.point<0){
System.out.println("余额不足,文件下载失败!");
this.point+=score;
}else if(this.point<100){
forumAccount.setState(new PrimaryState(this));
}
}
}
超级会员类
public class HightState extends AbstractState {
public HightState(AbstractState state) {
this.forumAccount=state.forumAccount;
this.point=state.getPoint();
this.stateName="专家";
}
public void writeNote(int score){
System.out.println(forumAccount.getName()+"发布留言,增加积分"+score+"*2个积分.");
this.point+=score*2;
this.checkState(score);
System.out.println("剩余积分为:"+this.point+",当前级别为:"+forumAccount.getState().stateName+".");
}
public void downLoadFile(int score){
System.out.println(forumAccount.getName()+"下载文件,扣除积分"+score+"/2积分。");
this.point-=score/2;
this.checkState(score);
System.out.println("剩余积分为:"+this.point+",当前级别为:"+forumAccount.getState().stateName+".");
}
@Override
public void checkState(int score) {
if(this.point<0){
System.out.println("余额不足,文件下载失败!");
this.point+=score;
}else if(this.point<=100){
forumAccount.setState(new PrimaryState(this));
}else if(this.point<=1000){
forumAccount.setState(new MiddleState(this));
}
}
}
测试类
public class TestStateDemo01 {
public static void main(String[] args) {
ForumAccount forumAccount=new ForumAccount("张三");
forumAccount.writeNote(20);
System.out.println("===============");
forumAccount.downLoadFile(20);
System.out.println("============");
forumAccount.replyNote(100);
System.out.println("=======");
forumAccount.writeNote(40);
System.out.println("=======");
forumAccount.downLoadFile(80);
System.out.println("=====");
forumAccount.downLoadFile(150);
System.out.println("=======");
forumAccount.writeNote(1000);
System.out.println("=======");
forumAccount.downLoadFile(80);
System.out.println("======");
}
}
运行结果:
张三注册成功!
================
张三发布留言,增加20积分。
剩余积分为:20,当前级别为:新手.
===============
对不起,张三您没有下载文件的权限!
============
张三回复留言,增加100积分。
剩余积分为:120,当前级别为:高手.
=======
张三发布留言,增加40*2个积分
剩余积分为:200,当前级别为:高手.
=======
张三下载文件,扣除80积分!
剩余积分为:120,当前级别 为:高手.
=====
张三下载文件,扣除150积分!
余额不足,文件下载失败!
剩余积分为:120,当前级别 为:高手.
=======
张三发布留言,增加1000*2个积分
剩余积分为:2120,当前级别为:专家.
=======
张三下载文件,扣除积分80/2积分。
剩余积分为:2080,当前级别为:专家.
======