35. 状态模式

作者: Next_吴思成 | 来源:发表于2018-07-24 22:18 被阅读1次

    定义

    状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States)。

    通俗理解

    “感觉不在状态,随时脉动回来!”,这个广告词随着脉动的广告铺天盖地地袭来,本来要扔飞机给心怡女生却扔给一个肌肉男的年轻男子、在图书馆不在状态把一排书给碰掉的大学生,在喝了脉动以后,都恢复了状态。用彩色的球球弹钢琴,潇洒地走掉不管那排倒了的书。

    在脉动广告里面有两种状态,一种是“在状态”,一种是“不在状态”,那么这种状态,是我们人里面的基本属性、还是外在属性?基本属性的含义是,人生来就有的,不需要外部去培养,不需要使用外界的眼光去判断的或者是有明确标准的。而外在属相就是,需要后台去培养,而且需要的眼光去判断并且没有明确标准的。这个有点绕,举个例子,例如我们的身高体重,不管我们怎么去看,我们的身高是1.7m就是1.7m,换个度量衡说8尺也行,就这个就是基本的属性,不需要使用外界的眼光去判断,有明确标准。那外在的属性呢?例如我们对某个孩子的评价,我们说,某个孩子很调皮,经常拆坏家里的电气。但是,调皮这个评价是孩子的内在评价么?我看不,我们也可以说这个孩子很有创造力。这样有不同标准的属性就是外在的属性。

    那么,“在状态”和“不在状态”,是什么属性?显然是外在的,我们可以去评价那个扔错飞机的人是一个“在状态的”,或许他就是想扔飞机给肌肉男,而用扔给女生作为一个接口。同时,我们也可以说他是不在状态的。

    具体表现在程序上,就是状态的属性,我们是使用基本类型(String也算是基本类型)去维护还是使用对象去维护。而状态模式的精髓,就在于我们使用一个对象类型去维护状态,而且这个对象还要是一个抽象类。

    示例

    业务按脉动来定义。

    渣渣程序

    public class Human {
        private String state;
        public Human(String state) {
            this.state = state;
        }
        public void drinkMaidong() {
            if("不在状态".equals(state)) {
                System.out.println("喝脉动");
                this.state = "在状态";
            } else {
                System.out.println("已经在状态了,不要再喝了");
            }
        }
        public void run() {
            if("在状态".equals(state)) {
                System.out.println("跑步");
                this.state = "不在状态";
            } else {
                System.out.println("不喝脉动就跑步,不行呀");
            }
        }
        public void checkState() {
            System.out.println(this.state);
        }
    }
    

    程序入口

    public class Main {
        static Human human = new Human("不在状态");
        public static void main(String[] args) {
            human.run();
            human.checkState();
            human.drinkMaidong();
            human.checkState();
        }
    }
    //不喝脉动就跑步,不行呀
    //不在状态
    //喝脉动
    //在状态
    

    好了,现在这代码出现了,不喝脉动就跑步,不行呀的情况,这明显不行哩,个人是判断不了自己在不在状态的,而且,如果我如果要加一个平时状态的话,我还得去改相关的代码,这是不合理的。问题就出在,我维护了状态,同时也维护了状态的改变。那么只需要把状态的改变提取到方法外面来,就可以了。

    优化

    类图

    代码

    状态接口以及实现

    public abstract class State {
        private String state;
        public String getState() {
            return state;
        }
        public void setState(String state) {
            this.state = state;
        }
        public void checkState() {
            System.out.println(state);
        }
    }
    public class TiredState extends State {
        static class SingletonHonlder {
            static  TiredState tiredState = new TiredState();
        }
        public static TiredState getTiredState() {
            return SingletonHonlder.tiredState;
        }
        private TiredState() {
            this.setState("不在状态");
        }
    }
    //WakeUpState类似
    

    public class Human {
        private State state;
        public State getState() {
            return state;
        }
        public void setState(State state) {
            this.state = state;
        }
        public void checkState() {
            this.state.checkState();
        }
    }
    

    程序入口

    public class Main {
        static Human human = new Human();
        public static void main(String[] args) {
            human.setState(TiredState.getTiredState());
            human.checkState();
            human.setState(WakeUpState.getTiredState());
            human.checkState();
        }
    }
    //不在状态
    //在状态
    

    现在状态有专门的维护,而且状态也可以在外部去改变,不管是喝脉动还是可口可乐,都能让这种状态进行变动,而且如果要加状态,就只需要加类就可以了,通过增加类的方式,我们实现了状态模式。

    优点

    1. 封装转换过程;
    2. 聚合了状态对象,操作委托给子类,简化代码。

    缺点

    1. 一个状态就是一个类,类真™的多。

    应用场景

    1. 状态很重要,行为取决于状态的;
    2. 操作中有多分支语句,而且分支依赖状态。

    程序

    e35_state_pattern

    吐槽

    还是会用枚举来表示状态,数据库存一个int类型表示不同的状态,对象?对数据库太不友好了。

    https://www.jianshu.com/p/0b9f16d360cf

    相关文章

      网友评论

        本文标题:35. 状态模式

        本文链接:https://www.haomeiwen.com/subject/qfhcpftx.html