1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

设计模式详解——状态模式

前言

今天我们来看一个号称策略模式双胞胎的设计模式——状态模式,如它的名字一样,状态模式最核心的设计思路就是将对象的状态抽象出一个接口,然后根据它的不同状态封装其行为,这样就可以实现状态和行为的绑定,最终实现对象和状态的有效解耦。下面我们就来详细看下它的基本原理和实现过程吧。

状态模式

状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

要点

  • 状态模式允许一个对象基于内部状态而拥有不同的行为
  • 和程序状态机(PSM)不同,状态模式用类代表状态
  • Context会将行为委托给当前状态对象
  • 通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了
  • 状态模式和策略模式有相同的类图,但是它们的意图不同
  • 策略模式通常会用行为或算法来配置Context
  • 状态模式允许Context随着状态的改变而改变行为
  • 状态转换可以由State类或Context类控制
  • 使用状态模式通常会导致设计中类的数目大量增加
  • 状态类可以被多个Context示例共享

优缺点

优点
  1. 封装了转换规则。

  2. 枚举可能的状态,在枚举状态之前需要确定状态种类。

  3. 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。

  4. 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块

  5. 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点
  1. 状态模式的使用必然会增加系统类和对象的个数。
  2. 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
  3. 状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

使用场景

  1. 行为随状态改变而改变的场景。
  2. 条件、分支语句的代替者。

示例

状态接口

首先是状态接口,这个接口是给我们实际的状态对象继承的,这个接口有一个方法doAction,这个方法就是给不同的状态对象实现的,用于处理不同状态下的行为的。

public interface State {
    /**
     * 改变状态的操作
     * @param context
     */
    void doAction(Context context);
}
状态所属者

然后是我们的状态所属者,这个类有一个核心的属性就是我们的State接口。

public class Context {
    private State state;

    public Context(){}

    public void setState(State state){
        this.state = state;
    }

    public State getState(){
        return state;
    }
     @Override
    public String toString() {
        return "Context{" +
                "state=" + state +
                '}';
    }
}
状态实现

状态实现者继承了State接口,并实现了doAction方法,在方法内部可以对我们的状态所有者进行对应的操作。

这里是一个启动状态:

public class StopState implements State {

    private String name;

    public StopState() {
        this.name = "stop";
    }

    @Override
    public void doAction(Context context) {
        System.out.println("Context is in stop state");
        context.setState(this);
        System.out.println(context);
    }

    @Override
    public String toString() {
        return "StopState{" +
                "name='" + name + '\'' +
                '}';
    }
}

这里是停止状态

public class StartState implements State{

    private String name;

    public StartState() {
        this.name = "start";
    }

    @Override
    public void doAction(Context context) {
        System.out.println("Context is in start state");
        context.setState(this);
        System.out.println(context);
    }

    @Override
    public String toString() {
        return "StartState{" +
                "name='" + name + '\'' +
                '}';
    }
}
测试代码

这里分别实例化了容器和状态的示例,然后通过示例的doAction方法操作容器

@Test
    public void testState() {
        Context context = new Context();

        StartState startState = new StartState();
        startState.doAction(context);


        StopState stopState = new StopState();
        stopState.doAction(context);

    }
运行结果

可以看到,状态对象的doAction方法执行后,容器对应的状态也发生了改变:

好了,关于状态模式就先说这么多,接下来我们做一个简单的总结。

总结

有用过策略模式或者对策略模式比较熟悉的小伙伴应该发现了:策略模式其实和我们今天分析状态模式特别像,甚至连架构模式都是一样的,所以这里我们有必要说下它们的区别。

首先是策略模式,它其实是将不同的算法封装成不同的策略,然后在具体的策略中实现具体的行为,但是测试本身是被动被选择的,容器选择策略,调用过程发生在容器中,而且策略本身是入参;

而我们今天分析的状态模式,它是将不同状态对应的行为封装,然后由具体的状态操作容器,整个过程更像是状态主动发起的,由状态执行其自己的方法,入参是容器。

这两种设计模式从某种程度上说是可以互相替换的,但是还是要结合具体业务分析的,比如spring boot启动过程中,它用到的就是状态模式,这一点我们在分析spring boot启动过程中也发现了;但如果是涉及到算法层面的内容,比如两个数的加减乘除,显然策略模式才是更好的选择。

总之,学习设计模式除了要了解它的基本原理和应用场景之外,更重要的是,要学会辨识优秀框架中的设计模式(知识,知就是知道,了解,识局势辨识,分析),最终将这些设计模式应用到我们的业务开发之中。

posted @ 2021-10-23 22:30  云中志  阅读(248)  评论(0编辑  收藏  举报