设计模式状态模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

网友投稿 504 2022-05-30

文章目录

一、状态模式简介

二、状态模式适用场景

三、状态模式优缺点

四、状态模式相关设计模式

五、状态模式代码示例

1、状态类父类

2、播放状态类

3、暂停状态类

4、快进状态类

5、停止状态类

6、上下文控制类

7、测试

一、状态模式简介

状态模式 : 允许 对象 在

内部状态 改变时 ,

改变它的行为 ;

一个对象 , 如果其

内部状态改变

, 其

行为也需要进行改变

; 如果其行为不需要改变 , 也可以只

控制 该对象的状态 的 互相转换 ;

当控制一个对象 , 其状态转换过程比较复杂时 , 将

状态判断逻辑 ,

转到代表不同状态的一系列类中 ;

如 : 引入 视频播放 的业务场景 , 播放器有 初始状态 , 播放状态 , 暂停状态 , 停止状态 , 快进状态 等多种状态 , 将这些

状态

都封装到

代表不同状态的类

中 , 可以将复杂的判断逻辑简化 , 将这些

逻辑

扩展到不同的状态类中 ;

状态模式类型 : 行为型 ;

二、状态模式适用场景

状态模式适用场景 : 一个对象 ,

存在多个状态 ,

状态可以相互转换 ;

不同状态下 ,

行为不同 ;

不同状态下 , 行为不同的示例 , 如 :

购买物品 , 将物品放入购物车并生成订单 , 可以进行付款 ; 如果 订单 超过 24 小时后 , 被关闭订单 , 此时订单取消 , 无法付款 ;

电梯运行时 , 不能开门 ; 电梯停止后 , 才能开门 ;

三、状态模式优缺点

状态模式优点 :

可以将

不同的状态

隔离

; 每个状态都是一个单独的类 ;

可以将 各种状态 的

转换逻辑

,

分布到 状态 的子类中 ,

减少相互依赖 ;

增加 新状态 , 操作简单 ;

状态模式缺点 :

如果

状态数量 比较多

,

状态类 的 数量会增加

,

业务场景系统变得很复杂

; 如果业务中某个对象由几十上百个状态 , 就会很复杂 , 这时就需要对状态进行拆分处理 ;

四、状态模式相关设计模式

状态模式 与 享元模式 , 可以配合在一起使用 , 可以使用享元模式 ,

在多个上下文中 ,

共享状态实例 ;

五、状态模式代码示例

业务场景 :

视频播放器 , 有 : 暂停 , 播放 , 快进 , 停止 , 四个状态 ;

在 停止 状态下 , 无法快进 , 如果当前是 停止 状态 , 此时要转为 快进 状态 , 需要进行校验 ;

如果不使用 状态模式 , 则需要进行 if else 判断 ;

如果使用 状态模式 , 就很容易实现 ;

状态类 :

定义状态父类抽象类 , 抽象方法是各个状态对应的方法 ;

定义状态子类 , 每个状态对应一个子类对象 ;

上下文类 :

在该类中封装 所有的状态实例 , 以及定义 状态改变方法 ;

封装当前状态类 , 状态改变方法 调用时 , 实际上调用的是 当前状态类的 对应方法 ;

1、状态类父类

package state; /** * 视频状态 父类 * 所有的视频状态 , 都要继承该类 */ public abstract class VedioState { /** * 视频播放上下文 * 声明为 protected , 子类可以拿到该成员变量 */ protected VedioContext vedioContext; public void setVedioContext(VedioContext vedioContext) { this.vedioContext = vedioContext; } /** * 播放 * 对应播放状态 */ public abstract void play(); /** * 停止 * 对应停止状态 */ public abstract void pause(); /** * 快进 * 对应快进状态 */ public abstract void speed(); /** * 停止 * 对应停止状态 */ public abstract void stop(); }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

2、播放状态类

package state; /** * 视频的播放状态 * 可以进行 快进 , 暂停 , 停止 操作 */ public class PlayState extends VedioState{ @Override public void play() { System.out.println("正常播放视频"); } /** * 暂停时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 暂停 的状态即可 */ @Override public void pause() { super.vedioContext.setVedioState(VedioContext.PAUSE_STATE); } /** * 快进时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 快进 的状态即可 */ @Override public void speed() { super.vedioContext.setVedioState(VedioContext.SPEED_STATE); } /** * 停止时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 停止 的状态即可 */ @Override public void stop() { super.vedioContext.setVedioState(VedioContext.STOP_STATE); } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

3、暂停状态类

package state; /** * 视频暂停状态 * 暂停状态 可以 切换到 播放 , 快进 , 停止 状态 */ public class PauseState extends VedioState{ /** * 播放时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 播放 的状态即可 */ @Override public void play() { super.vedioContext.setVedioState(VedioContext.PLAY_STATE); } /** * 暂停时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 暂停 的状态即可 */ @Override public void pause() { System.out.println("暂停播放视频"); } /** * 快进时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 快进 的状态即可 */ @Override public void speed() { super.vedioContext.setVedioState(VedioContext.SPEED_STATE); } /** * 停止时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 停止 的状态即可 */ @Override public void stop() { super.vedioContext.setVedioState(VedioContext.STOP_STATE); } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

4、快进状态类

package state; /** * 视频快进状态 * 快进状态下 , 可以进行 播放 , 暂停 , 停止操作 */ public class SpeedState extends VedioState{ /** * 播放时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 播放 的状态即可 */ @Override public void play() { super.vedioContext.setVedioState(VedioContext.PLAY_STATE); } /** * 暂停时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 暂停 的状态即可 */ @Override public void pause() { System.out.println("快进播放视频"); } /** * 快进时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 快进 的状态即可 */ @Override public void speed() { super.vedioContext.setVedioState(VedioContext.SPEED_STATE); } /** * 停止时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 停止 的状态即可 */ @Override public void stop() { super.vedioContext.setVedioState(VedioContext.STOP_STATE); } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

5、停止状态类

package state; /** * 视频的停止状态 * 可以进行 播放 操作 * 不能进行 快进 , 暂停 操作 */ public class StopState extends VedioState{ /** * 播放时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 播放 的状态即可 */ @Override public void play() { super.vedioContext.setVedioState(VedioContext.PLAY_STATE); } /** * 不能暂停 */ @Override public void pause() { System.out.println("停止状态不能暂停"); } /** * 不能快进 */ @Override public void speed() { System.out.println("停止状态不能快进"); } /** * 停止时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext * 将上下文 VedioContext 中的状态 , 设置为 停止 的状态即可 */ @Override public void stop() { System.out.println("停止播放视频"); } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

【设计模式】状态模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

6、上下文控制类

package state; /** * 使用享元模式 , 共享同一个对象 * * 上下文也有 play , pause , speed , stop 等状态 * 执行这些方法时 , 调用状态的相应方法 */ public class VedioContext { /** * 当前的状态 */ private VedioState mVedioState; public final static PlayState PLAY_STATE = new PlayState(); public final static PauseState PAUSE_STATE = new PauseState(); public final static SpeedState SPEED_STATE = new SpeedState(); public final static StopState STOP_STATE = new StopState(); public VedioState getVedioState() { return mVedioState; } /** * 将传入的 VedioState , 赋值给当前的 VedioState mVedioState 成员 * 除此之外 , 还要设置 VedioState 的上下文 , 即该类本身 * 将当前的环境 VedioContext , 通知到各个状态实现类 * @param mVedioState */ public void setVedioState(VedioState mVedioState) { this.mVedioState = mVedioState; this.mVedioState.setVedioContext(this); } public void play() { this.mVedioState.play(); } public void pause() { this.mVedioState.pause(); } public void speed() { this.mVedioState.speed(); } public void stop() { this.mVedioState.stop(); } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

7、测试

package state; public class Main { public static void main(String[] args) { VedioContext vedioContext = new VedioContext(); vedioContext.setVedioState(VedioContext.PLAY_STATE); System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName()); vedioContext.pause(); System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName()); vedioContext.speed(); System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName()); vedioContext.stop(); System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName()); vedioContext.speed(); System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName()); } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

执行结果 :

视频

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:计算机入门网络知识——码民薄见
下一篇:移动办公OA会议管理方案:大、小会议轻松管,高效开
相关文章