• 23【状态设计模式】



    二十三、状态设计模式

    23.1 状态设计模式简介

    23.1.1 状态设计模式概述

    状态设计模式(State Pattern):允许对象在内部状态发生改变时,改变他的行为,对象看起来好像修改了它的类;

    状态模式中类的行为是由状态来决定的,在不同的状态下有不同的行为。其核心是让一个对象在其内部改变的时候,行为也随之改变。状态模式关注的核心点时将状态与行为进行绑定,不同的状态具备不同的行为

    【场景举例】

    状态模式在我们生活中比较常见

    • 例1:如某个社交网站中,普通用户的权限为发布文章、浏览文章、使用限定皮肤,而VIP用户可以发布付费文章、浏览付费资源、使用更加精美的皮肤;普通用户和VIP用户这就是两个状态,不同状态可以做的事情(行为)是不一样的;
    • 例2:在网站中,未登录的用户可以浏览文章、查看评论等,登录过后的用户权限更加多,还可以点赞文章、收藏文章、发布评论等;登录的用户和未登录的用户就是两个状态,不同状态可以做的事情(行为)是不一样的;

    状态模式要实现的就是一个操作一个对象时,其内部自动发生状态改变,看起来好像是修改了其他类一样;

    23.1.2 状态设计模式的UML类图

    状态设计模式中主要有3个角色:

    • 1)环境角色(Context):也称为上下文,它定义了客户程序需要的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
    • 2)抽象状态角色(State):定义一个接口,用以封装环境对象中的特定状态所对应的行为。
    • 3)具体状态角色(ConcreteState):实现抽象状态所对应的行为。

    在这里插入图片描述

    23.2 状态设计模式的实现

    【案例】

    在网站中,未登录的用户可以浏览文章、查看评论等,登录过后的用户权限更加多,还可以点赞文章、收藏文章等;如果在未登录状态下点赞文章,一般网站会弹出登录框提醒用户登录,用户登录过后具备点赞文章、收藏文章等功能;

    下面我们使用状态模式来实现上述案例;

    • 1)抽象状态:
    package com.pattern.demo01;
    
    /**
     * @author lscl
     * @version 1.0
     * @intro: 抽象状态
     */
    public abstract class AbstractUserState {
    
        protected Context context;
    
        public void setContext(Context context) {
            this.context = context;
        }
    
        // 点赞操作
        public abstract void thumbup();
    
        // 收藏操作
        public abstract void favorite();
    }
    
    • 2)登录状态(具体状态):
    package com.pattern.demo01;
    
    /**
     * @author lscl
     * @version 1.0
     * @intro: 具体状态
     */
    public class LoginState extends AbstractUserState {
        @Override
        public void thumbup() {
            System.out.println("点赞成功!");
        }
    
        @Override
        public void favorite() {
            System.out.println("收藏成功!");
        }
    }
    
    • 3)未登录状态(具体状态):
    package com.pattern.demo01;
    
    /**
     * @author lscl
     * @version 1.0
     * @intro:
     */
    public class UnLoginState extends AbstractUserState {
        @Override
        public void thumbup() {
            toLogin();
            System.out.println("点赞成功!");
        }
    
        @Override
        public void favorite() {
            toLogin();
            System.out.println("收藏成功!");
        }
    
        private void toLogin(){
            System.out.println("欢迎来到登录页面!");
            System.out.println("登录成功....");
    
            // 将状态设置为登录状态
            this.context.setState(this.context.LOGIN_STATE);
        }
    }
    
    • 4)上下文角色:
    package com.pattern.demo01;
    
    /**
     * @author lscl
     * @version 1.0
     * @intro: 上下文对象对具体的状态进行管理
     */
    public class Context {
    
        // 登录的状态
        public static final AbstractUserState LOGIN_STATE = new LoginState();
    
        // 未登录的状态
        public static final AbstractUserState UNLOGIN_STATE = new UnLoginState();
    
        // 当前状态(默认为未登录)
        private AbstractUserState currentState = UNLOGIN_STATE;
    
        {
            // 初始化上下文
            LOGIN_STATE.setContext(this);
            UNLOGIN_STATE.setContext(this);
        }
    
        public void setState(AbstractUserState userState) {
            this.currentState = userState;
            this.currentState.setContext(this);
        }
    
        public void favorite() {
            // 调用当前状态进行收藏
            this.currentState.favorite();
        }
    
        public void thumbup() {
            // 调用当前状态进行点赞
            this.currentState.thumbup();
        }
    }
    
    • 5)测试类:
    package com.pattern.demo01;
    
    /**
     * @author lscl
     * @version 1.0
     * @intro:
     */
    public class Demo01 {
        public static void main(String[] args) {
    
            // 创建上下文对象,包含多种状态
            Context context=new Context();
    
            // 使用上下文中的默认状态进行操作,如果发现当前状态不具备操作的权限将会自动切换状态,给用户感觉换了一个类一样
            context.favorite();
            context.thumbup();
        }
    }
    

    23.3 状态设计模式的优缺点

    • 优点:
      • 1)将状态转换显示化:通常对象的状态都是通过赋值进行表现,不够直观。而使用状态类,当状态切换时,是以不同的类进行表示的,转换目的更加明确;
      • 2)状态类职责明确,且具备扩展性;符合单一职责原则
    • 缺点:
      • 1)类膨胀:如果一类事物具备过多的状态,则会造成类的数量过多
      • 2)虽然支持新增状态,这方面扩展性好;但是在新增状态时,需要修改原先状态切换部分的源码,否则状态也不能切换到新定义的状态,这方面扩展性差,不符合开闭原则;
  • 相关阅读:
    二十三、SpringBoot + Jwt + Vue 权限管理系统 (4)
    混合优化算法(optimtool.hybrid)
    【frida】HLL 登录流程分析 找关键 Call
    springboot悠悠转二手网站毕业设计源码181134
    【Spring Cloud】网关Gateway的请求过滤工厂RequestRateLimiterGatewayFilterFactory
    设计模式-创建型模式
    (附源码)计算机毕业设计ssmJAVA高校田径运动会管理
    Neo4j入门教程2(看不懂评论区随便骂)
    2023互联网中秋礼盒大比拼!
    解密Prompt系列23.大模型幻觉分类&归因&检测&缓解方案脑图全梳理
  • 原文地址:https://blog.csdn.net/Bb15070047748/article/details/127095816