0%

设计模式之行为型模式(八):状态模式

1. 状态模式概述

  • 概述

    • 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类
    • 状态模式就是一个关于多态的设计模式,《代码整洁之道》和《重构》都提到:应使用多态取代条件表达式
  • 特点

    • 优点:将与特定状态相关的行为封装到一个状态对象中,使用多态代替 if-else 或者 switch-case 状态判断
    • 缺点:必然导致类增加,这也是使用多态不可避免的问题
  • Demo

    • 定义一个用户状态枚举类

      1
      2
      3
      public enum State {
      NORMAL, PLUS
      }
    • 用户的功能接口

      1
      2
      3
      public interface IUser {
      void mockInterview();
      }
    • 用户状态切换接口

      1
      2
      3
      4
      5
      public interface ISwitchState {
      void purchasePlus();

      void expire();
      }
    • 力扣用户类

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      public class User implements IUser, ISwitchState {
      private State state = State.NORMAL;

      @Override
      public void mockInterview() {
      if (state == State.PLUS) {
      System.out.println("开始模拟面试");
      } else {
      System.out.println("模拟面试是 Plus 会员专享功能");
      }
      }

      @Override
      public void purchasePlus() {
      state = State.PLUS;
      }

      @Override
      public void expire() {
      state = State.NORMAL;
      }
      }
      • 判断用户状态会产生大量的分支判断语句,导致代码冗长
      • 当状态有增加或减少时,需要改动多个地方,违反开闭原则
    • 利用多态特性重构,为每个状态新建一个状态类。普通用户

      1
      2
      3
      4
      5
      6
      7
      class Normal implements IUser {

      @Override
      public void mockInterview() {
      System.out.println("模拟面试是 Plus 会员专享功能");
      }
      }
    • PLUS 会员

      1
      2
      3
      4
      5
      6
      7
      class Plus implements IUser {

      @Override
      public void mockInterview() {
      System.out.println("开始模拟面试");
      }
      }
    • 使用状态模式的用户类

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      class User implements IUser, ISwitchState {

      IUser state = new Normal();

      @Override
      public void mockInterview() {
      state.mockInterview(); // 丑陋的状态判断语句消失了
      }

      @Override
      public void purchasePlus() {
      state = new Plus();
      }

      @Override
      public void expire() {
      state = new Normal();
      }
      }
    • 客户端测试

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      public class Client {

      @Test
      public void test() {
      // 用户初始状态为普通用户
      User user = new User();
      // 输出:模拟面试是 Plus 会员专享功能
      user.mockInterview();

      // 用户购买 Plus 会员,状态改变
      user.purchasePlus();
      // 输出:开始模拟面试
      user.mockInterview();

      // Plus 会员过期,变成普通用户,状态改变
      user.expire();
      // 输出:模拟面试是 Plus 会员专享功能
      user.mockInterview();
      }
      }
-------------------- 本文结束感谢您的阅读 --------------------