介绍:状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行动模式。状态模式把所研究的对象的行动包装在不同的状态对象里,每个状态对象都属于1个抽象状态类的1个子类。
作用:状态模式的意图是根据状态来分离和选择行动,让1个对象在其内部状态改变的时候,其行动也随之改变。
场景:有些生存类游戏,比如《饥荒》,在场景中会有很多非1次性互动物品,如树木,草等,它们会定时枯萎,生长。
就树而言可以分为下面状态:生长—结果—灭亡
可能在1个业务中,我们会有很多if—else等。可能原来的逻辑是正确的,但是如果我们在里面增加功能,对逻辑进行修改,就会10分麻烦。这个时候就能够用状态模式。
角色 | 作用 |
---|---|
环境(Context) | 也称上下文,状态决定它的现状 |
抽象状态(State) | 定义1个接口,用以封装环境(Context)对象的1个特定的状态所对应的行动 |
具体状态(ConcreteState) | 每个具体状态类都实现了环境(Context)的1个状态所对应的行动 |
环境角色
(树)保存了1生所有可能经历的状态,基因决定了树木生长和结果最大年龄。
public class Tree {
// 持有1个State类型的对象实例
private TreeState state;
// 保存树木1生所有的状态
public Map<String, TreeState> states = new HashMap<String, TreeState>();
public int growSize; // 生长可能时间
public int fruitSize; // 结果可能时间
public int now = 1; // 树木年龄
public Tree() {
states.put("grow", new GrowState(this));
states.put("fruit", new FruitState(this));
states.put("death", new DeathState(this));
this.state = states.get("grow");
// 如果没有环境因素,植物生长和结果是由基因决定的,生长最多5年,最多2年结果
Random random =new Random();
growSize =random.nextInt(5);
fruitSize = random.nextInt(2);
}
public void setState(TreeState state) {
this.state = state;
}
public void handle() {
state.handle();
}
}
状态
public interface TreeState {
public void handle();
}
生长状态
树木如果生长到1定年龄,进入结果状态
public class GrowState implements TreeState {
private Tree tree;
public GrowState(Tree tree) {
this.tree = tree;
}
@Override
public void handle() {
if (tree.now < tree.growSize) {
System.out.println("植物长大");
tree.now++;
} else {
tree.setState(tree.states.get("fruit"));
}
}
}
结果状态
如果超过结果年龄,树木进入死亡状态
public class FruitState implements TreeState {
private Tree tree;
public FruitState(Tree tree) {
this.tree = tree;
}
@Override
public void handle() {
if (tree.now < (tree.growSize + tree.fruitSize)) {
System.out.println("植物结果");
tree.now++;
} else {
tree.setState(tree.states.get("death"));
}
}
}
死亡状态
public class DeathState implements TreeState {
private Tree tree;
public DeathState(Tree tree) {
this.tree = tree;
}
@Override
public void handle() {
System.out.println("植物已死亡");
tree.setState(tree.states.get("death"));
}
}
摹拟生长
某1颗树的1生
Tree tree = new Tree();
while (true) {
tree.handle();
}
进程
植物长大
植物长大
植物长大
植物结果
植物已死亡
缺点
- 会增加类和对象的个数,如果使用不当会造成逻辑混乱。
- 状态模式对“开闭原则”的支持其实不太好,增加新的状态类需要修改那些负责状态转换的源代码
在网上学习其他大神博客的时候看到很多评论,这不是状态模式是策略模式,或这不是策略模式是状态模式,不要误人子弟。但是其实博主是正确的,而那些言语粗鲁的人反而是自己无知(让我10分反感)。状态模式常常与策略模式相混淆。1个简单的方法是考察环境角色是不是有明显的状态和状态的过渡。
状态模式:
状态模式处理的核心问题是状态的迁移,由于在对象存在很多状态情况下,各个状态之间跳转和迁移进程都是及其复杂的。在状态模式中,状态改变是由对象的内部条件决定,外界只需关心其接口,没必要关心其状态对象的创建和转化。
策略模式:
策略模式的好处在于你可以动态的改变对象的策略行动。策略模式里,采取何种策略由外部条件决定,也就是说使用甚么策略由我们来提供,而策略的具体实现类实现对应算法。比如1种商品,我们可以有很多降价和提价策略,我们只需要定义好各种策略的规则,然后让商品去履行就好了。
更多模式:http://blog.csdn.net/odeviloo/article/details/52382338
更多源码:https://github.com/oDevilo/Java-Base