声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/
/*
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类
状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况
把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化
如果在某段代码中if-else或者switch语句过多,老鸟们常常建议说,可以采用策略模式或者状态模式来重构
在我看来,策略模式仍然需要作if-else的判断,除非需求已明确指出要采用哪个策略
但状态模式似乎更好一些
书上关于用户投票的例子,对我这样的设计模式初学者来说,还是略嫌复杂
网上有一个更简单明了的例子:
http://www.riabook.cn/doc/designpattern/StatePattern.htm
依照上面链接的例子,我写了一个简单示例:
public class StatePatternLjn {
public static void main(String[] args) {
SomeObject obj = new SomeObject();
obj.change();
obj.change();
obj.change();
obj.change();
}
}
interface State {
void changeState(SomeObject obj);
}
class SomeObject {
private State state;
public SomeObject() {
state = new Astate();
}
public void setState(State state) {
this.state = state;
}
public void change() {
this.state.changeState(this);
}
}
class Astate implements State {
public void changeState(SomeObject obj) {
obj.setState(new Bstate());
System.out.println("a -> b");
}
}
class Bstate implements State{
public void changeState(SomeObject obj) {
obj.setState(new Cstate());
System.out.println("b -> c");
}
}
class Cstate implements State{
public void changeState(SomeObject obj) {
obj.setState(new Astate());
System.out.println("c -> a");
}
}
和Strategy模式有很多相似的地方,需要说明的是两者的思想都是一致的,只不过封装的东西不同:
State模式封装的是不同的状态,而Stategy模式封装的是不同的算法
*/
import java.util.HashMap;
import java.util.Map;
/*
* 考虑一个投票的应用:
* 一个用户只能投一票,若一个用户反复投票,而且投票次数超过5,则认为是恶意刷票,撤消投票记录并取消投票资格
* 若超过8次,则加入黑名单并禁止再使用系统
*/
interface IVoteState {
/**
* @param user 投票的用户
* @param voteItem 投票选项
* @param context
*/
public void vote(String user, String voteItem, VoteContext context);
}
//正常投票
class NormalVoteState implements IVoteState {
public void vote(String user, String voteItem, VoteContext context) {
context.getMapVoteItem().put(user, voteItem);
System.out.println("投票成功");
}
}
//重复投票
class RepeatVoteState implements IVoteState {
public void vote(String user, String voteItem, VoteContext context) {
System.out.println("请不要重复投票");
}
}
//恶意投票
class SpiteVoteState implements IVoteState {
public void vote(String user, String voteItem, VoteContext context) {
context.getMapVoteItem().remove(user);
System.out.println("你有恶意刷票行为,取消投票资格!");
}
}
//黑名单
class BlackVoteState implements IVoteState {
public void vote(String user, String voteItem, VoteContext context) {
System.out.println("进入黑名单");
}
}
class VoteContext {
//通常会维护(持有)一个State对象
private IVoteState state;
//Map<用户,投票项>
private Map<String, String> mapVoteItem = new HashMap<String, String>();
//Map<用户,投票次数>
private Map<String, Integer> mapVoteCount = new HashMap<String, Integer>();
//在Context里面进行状态的切换
public void vote(String user, String voteItem) {
Integer voteCount = mapVoteCount.get(user);
if (voteCount == null) {
voteCount = 0;
}
voteCount++;
mapVoteCount.put(user, voteCount);
if (voteCount == 1) {
state = new NormalVoteState();
} else if (voteCount > 1 && voteCount < 5) {
state = new RepeatVoteState();
} else if (voteCount >= 5 && voteCount < 8) {
state = new SpiteVoteState();
} else if (voteCount >= 8) {
state = new BlackVoteState();
}
state.vote(user, voteItem, this);
}
public Map<String, String> getMapVoteItem() {
return mapVoteItem;
}
}
/*
* 假如我们现在有这样一个需求:投票成功的用户将获得积分奖励,那就势必要更改VoteContext的Vote方法:
if (voteCount == 1) {
state = new NormalVoteStateWithPrice();
}
......
* 这就是书上说的不完美的OCP体验
*/
class NormalVoteStateWithPrice extends NormalVoteState {
public void vote(String user, String voteItem, VoteContext context) {
super.vote(user, voteItem, context);
System.out.println("奖励积分:10");
}
}
/*
* 上面的示例,是在Context里面进行状态的切换
* 状态的切换也可以在状态的处理类中实现
* 这种情况下,若有新的需求(例如新增一种状态),则可增加一个IVoteState而不必修改已有代码
*/
interface IVoteStatee {
public void vote(String user, String voteItem, VoteContextt context);
}
//正常投票
class NormalVoteStatee implements IVoteStatee {
public void vote(String user, String voteItem, VoteContextt context) {
context.getMapVoteItem().put(user, voteItem);
System.out.println("投票成功");
//正常投票完成,维护下一个状态,同一个人再投票就重复了
context.getMapState().put(user, new RepeatVoteStatee());
}
}
//重复投票
class RepeatVoteStatee implements IVoteStatee {
public void vote(String user, String voteItem, VoteContextt context) {
System.out.println("请不要重复投票");
if (context.getMapVoteCount().get(user) >= 4) {
context.getMapState().put(user, new SpiteVoteStatee());
}
}
}
//恶意投票
class SpiteVoteStatee implements IVoteStatee {
public void vote(String user, String voteItem, VoteContextt context) {
context.getMapVoteItem().remove(user);
System.out.println("你有恶意刷票行为,取消投票资格!");
if (context.getMapVoteCount().get(user) >= 7) {
context.getMapState().put(user, new BlackVoteStatee());
}
}
}
//黑名单
class BlackVoteStatee implements IVoteStatee {
public void vote(String user, String voteItem, VoteContextt context) {
System.out.println("进入黑名单");
}
}
class VoteContextt {
//Map<用户,本用户投票后对应的状态>
private Map<String, IVoteStatee> mapState = new HashMap<String, IVoteStatee>();
//Map<用户,投票项>
private Map<String, String> mapVoteItem = new HashMap<String, String>();
//Map<用户,投票次数>
private Map<String, Integer> mapVoteCount = new HashMap<String, Integer>();
public void vote(String user, String voteItem) {
//1.投票数加1
Integer voteCount = mapVoteCount.get(user);
if (voteCount == null) {
voteCount = 0;
}
voteCount++;
mapVoteCount.put(user, voteCount);
//2.维护状态
IVoteStatee state = mapState.get(user);
if (state == null) {
state = new NormalVoteStatee();
}
state.vote(user, voteItem, this);
}
public Map<String, IVoteStatee> getMapState() {
return mapState;
}
public Map<String, String> getMapVoteItem() {
return mapVoteItem;
}
public Map<String, Integer> getMapVoteCount() {
return mapVoteCount;
}
}
//这个类是用来测试的
public class StatePattern {
public static void main(String[] args) {
//测试-状态切换在Context里实现
VoteContext context = new VoteContext();
for (int i = 0; i < 8; i++) {
context.vote("Tom", "A");
}
System.out.println();
//测试-状态切换由状态实现类切换
VoteContextt contextt = new VoteContextt();
for (int i = 0; i < 8; i++) {
contextt.vote("Tom", "A");
}
}
}