笔头云 笔头云
首页
设计模式
SQL教程
Redis
归档
关于
友链

笔头云

非淡泊无以明志,非宁静无以致远。
首页
设计模式
SQL教程
Redis
归档
关于
友链
  • 设计原则
  • 设计模式
  • 单例模式
  • 工厂模式
  • 建造者模式
  • 原型模式
  • 适配器模式
  • 代理模式
  • 装饰器模式
  • 门面模式
  • 桥接模式
  • 享元模式
  • 组合模式
  • 策略模式
  • 模板方法模式
  • 观察者模式
  • 责任链模式
  • 状态模式
    • 定义
    • 结构
    • 优点
    • 缺点
    • 应用场景
    • 示例代码
  • 迭代器模式
  • 访问者模式
  • 中介模式
  • 命令模式
  • 解释器模式
  • 备忘录模式
  • 设计模式
笔头云
2023-11-02
目录

状态模式

# 状态模式

状态模式通过将对象的行为封装在不同的状态对象中,使得对象能够根据内部状态的改变而改变行为,从而实现了对象的状态和行为的松耦合。

# 定义

状态模式是一种行为设计模式,它允许对象在内部状态发生改变时改变其行为,看起来好像是对象在运行时改变了其类。状态模式将对象的行为封装在不同的状态对象中,使得对象根据其当前状态而具有不同的行为。

状态模式和策略模式的区别

状态模式(State Pattern)和策略模式(Strategy Pattern)的主要区别在于它们关注的问题领域和解决的问题类型。状态模式关注对象内部的状态变化,策略模式关注选择和切换不同的算法或策略。
状态模式关注对象的内部状态的变化和行为的变化,它通过封装状态为独立类来实现状态之间的切换。而策略模式关注选择和切换不同的算法或策略,它通过封装算法或策略为独立类来实现策略的选择和切换。

# 结构

上下文(Context):上下文是拥有状态的对象,它维护一个对抽象状态对象的引用,并在运行时根据当前状态调用相应的方法。上下文类提供了一些公共方法,供客户端代码调用以改变状态。
抽象状态(Abstract State):抽象状态是一个抽象类或接口,定义了状态对象的共同接口和方法。它包含了在不同状态下可能发生的行为,并定义了在上下文中触发状态转换的方法。
具体状态(Concrete State):具体状态是抽象状态的子类,它实现了抽象状态定义的方法,并根据当前状态下的需求提供具体的行为。每个具体状态类负责管理在特定状态下对象的行为。

状态模式

- img: https://bitouyun.com/images/design-pattern/state.png
  link: https://bitouyun.com/images/design-pattern/state.png
  name: 状态模式
1
2
3

# 优点

提高可维护性:状态模式将每个状态的行为封装在具体状态类中,使得每个状态都可以独立变化,易于添加新的状态或修改现有状态的行为。
提高可扩展性:由于状态的变化和行为的变化被封装在具体状态类中,因此在需要添加新的状态或修改现有状态的行为时,不需要修改上下文类的代码,符合开闭原则。
消除条件语句:状态模式通过将状态的判断逻辑转移到状态类内部,减少了在上下文类中使用大量的条件语句,提高了代码的可读性和可维护性。
易于理解和调试:状态模式将状态转换逻辑集中到具体状态类中,使得状态的转换变得可见和可控,易于理解和调试。

# 缺点

增加了类和对象的数量:引入状态模式会增加具体状态类的数量,可能会导致类的数量增加,从而增加系统的复杂性。
状态切换的开销:在状态模式中,状态的切换需要在上下文类和具体状态类之间进行通信,可能会增加一定的开销,特别是当状态比较多或者状态切换比较频繁时。

# 应用场景

状态模式适用于具有多个状态和状态转换的场景,可以提高代码的可读性、可维护性和扩展性。但是,在状态比较简单或者状态转换较少的情况下,引入状态模式可能会增加不必要的复杂性。
对象的行为取决于其内部状态,并且该行为在运行时可能发生改变。
有多个状态且状态之间存在复杂的转换关系。
需要消除条件语句,并且条件语句的判断逻辑与状态相关。
需要在运行时动态地添加新的状态或修改现有状态的行为。
需要将状态的转换过程可见和可控,方便理解和调试。

# 示例代码

场景

系统用户登录状态的管理,包含未登录、已登录、已登出状态。应用程序可以根据用户登录状态执行不同的行为,并且状态的转换被封装在具体状态类中,使得状态变化的管理更加清晰和灵活。

    /**
     * 登录状态接口
     * 未登录、已登录、已登出
     */
    public interface LoginState {
      // 登录
      void login(String username, String password);
    
      // 登出
      void logout();
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
     * 未登录状态
     * 具体状态类
     */
    @Slf4j
    public class NotLoggedInState implements LoginState {
        @Override
        public void login(String username, String password) {
            if (username.equals("admin") && password.equals("123456")) {
                log.info("登录成功");
            } else {
                log.info("登录失败");
            }
        }
    
        @Override
        public void logout() {
            log.info("无法登出,请先登录系统");
        }
    }
    
    /**
     * 已登录状态
     * 具体实现类
     */
    @Slf4j
    public class LoggedInState implements LoginState {
        @Override
        public void login(String username, String password) {
            log.info("无法登录,用户已登录");
        }
    
        @Override
        public void logout() {
            log.info("用户登出");
        }
    }
    
    /**
     * 登录失败状态
     * 具体状态类
     */
    @Slf4j
    public class LoginFailedState implements LoginState {
        @Override
        public void login(String username, String password) {
            if (username.equals("admin") && password.equals("123456")) {
                log.info("登录成功");
            } else {
                log.info("登录失败");
            }
        }
    
        @Override
        public void logout() {
            log.info("无法登出,用户登录失败");
        }
    }
    
    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
    52
    53
    54
    55
    56
    57
    58
    /**
     * 用户上下文
     */
    public class UserContext {
        // 持有登录状态接口引用
        private LoginState loginState;
    
        public UserContext() {
            // 初始状态为:未登录状态
            this.loginState = new NotLoggedInState();
        }
        // 改变用户登录状态
        public void setLoginState(LoginState loginStatte) {
            this.loginState = loginStatte;
        }
    
        // 登录
        public void login(String username, String password) {
            loginState.login(username, password);
        }
    
        public void logout() {
            loginState.logout();
        }
    }
    
    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
    /**
     * 测试类
     */
    @Slf4j
    public class Client {
        public static void main(String[] args) {
            LoginState loggedInState = new LoggedInState();
            LoginState loginFailedState = new LoginFailedState();
    
            UserContext userContext = new UserContext();
            log.info("------(初始)未登录状态------");
            userContext.login("admin", "123456");
            userContext.logout();
    
            log.info("------登录状态------");
            userContext.setLoginState(loggedInState);
            userContext.login("admin", "123456");
            userContext.logout();
    
            log.info("------登录失败状态------");
            userContext.setLoginState(loginFailedState);
            userContext.login("admin", "123456");
            userContext.logout();
        }
    }
    
    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
    // Make sure to add code blocks to your code group
    #行为型模式#设计模式
    上次更新: 2023/11/17, 09:38:49
    责任链模式
    迭代器模式

    ← 责任链模式 迭代器模式→

    最近更新
    01
    FRP内网穿透docker部署 工具
    05-07
    02
    Office Util办公工具 工具
    01-14
    03
    Git常用命令
    01-16
    更多文章>
    Theme by Vdoing | Copyright © 2023-2025 鲁ICP备2023014898号 公安备案号:37020302372159
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式
    ×