一天一个设计模式---状态模式

介绍:状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式。状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。

作用:状态模式的意图是根据状态来分离和选择行为,让一个对象在其内部状态改变的时候,其行为也随之改变。

场景:有些生存类游戏,比如《饥荒》,在场景中会有很多非一次性互动物品,如树木,草等,它们会定时枯萎,生长。
就树而言可以分为下面状态:生长—结果—灭亡

一、角色及作用

可能在一个业务中,我们会有很多if—else等。可能原来的逻辑是正确的,但是如果我们在里面增加功能,对逻辑进行修改,就会十分麻烦。这个时候就可以用状态模式。

角色作用
环境(Context)也称上下文,状态决定它的现状
抽象状态(State)定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为
具体状态(ConcreteState)每一个具体状态类都实现了环境(Context)的一个状态所对应的行为

二、模拟一颗树的一生

环境角色

(树)保存了一生所有可能经历的状态,基因决定了树木生长和结果最大年龄。

public class Tree {
    // 持有一个State类型的对象实例
    private TreeState state;
    // 保存树木一生所有的状态
    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();
}

生长状态

树木如果生长到一定年龄,进入结果状态

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"));
    }
}

模拟生长

某一颗树的一生

Tree tree = new Tree();
    while (true) {
        tree.handle();
    }

过程

植物长大
植物长大
植物长大
植物结果
植物已死亡

缺点
- 会增加类和对象的个数,如果使用不当会造成逻辑混乱。
- 状态模式对“开闭原则”的支持并不太好,增加新的状态类需要修改那些负责状态转换的源代码

三、状态模式和策略模式的比较

在网上学习其他大神博客的时候看到很多评论,这不是状态模式是策略模式,或者这不是策略模式是状态模式,不要误人子弟。但是其实博主是正确的,而那些言语粗鲁的人反而是自己无知(让我十分反感)。状态模式经常与策略模式相混淆。一个简单的方法是考察环境角色是否有明显的状态和状态的过渡。

状态模式:

状态模式处理的核心问题是状态的迁移,因为在对象存在很多状态情况下,各个状态之间跳转和迁移过程都是及其复杂的。在状态模式中,状态改变是由对象的内部条件决定,外界只需关心其接口,不必关心其状态对象的创建和转化。

策略模式:

策略模式的好处在于你可以动态的改变对象的策略行为。策略模式里,采取何种策略由外部条件决定,也就是说使用什么策略由我们来提供,而策略的具体实现类实现对应算法。比如一种商品,我们可以有很多降价和提价策略,我们只需要定义好各种策略的规则,然后让商品去执行就行了。


更多模式: 一天一个设计模式—分类与六大原则

更多源码: https://github.com/oDevilo/Java-Base

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值