状态模式(二十四)

news2024/10/7 4:25:18

相信自己,请一定要相信自己

上一章简单介绍了 解释器模式(二十三), 如果没有看过, 请观看上一章

一. 状态模式

引用 菜鸟教程里面 状态模式介绍: https://www.runoob.com/design-pattern/state-pattern.html

在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。

在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。

一.一 介绍

意图: 允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。

主要解决: 对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。

何时使用: 代码中包含大量与对象状态有关的条件语句。

如何解决: 将各种具体的状态类抽象出来。

关键代码: 通常命令模式的接口中只有一个方法。而状态模式的接口中有一个或者多个方法。
而且,状态模式的实现类的方法,一般返回值,或者是改变实例变量的值。
也就是说,状态模式一般和对象的状态有关。实现类的方法有不同的功能,覆盖接口中的方法。
状态模式和命令模式一样,也可以用于消除 if…else 等条件选择语句。

应用实例:
1、打篮球的时候运动员可以有正常状态、不正常状态和超常状态。
2、曾侯乙编钟中,‘钟是抽象接口’,'钟A’等是具体状态,'曾侯乙编钟’是具体环境(Context)。

优点:
1、封装了转换规则。
2、枚举可能的状态,在枚举状态之前需要确定状态种类。
3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

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

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

注意事项: 在行为受状态约束的时候使用状态模式,而且状态不超过 5 个。


组成角色具体关系
抽象状态角色 (State)State抽象状态角色,负责对象状态定义,并且封装环境角色以实现状态切换
具体状态角色 (ConcreteState)NoChouState,CanChouState具体状态主要有两个职责:
一是处理本状态下的事情,二是从本状态如何过渡到其他状态
环境角色(Context)ActivityContext定义客户端需要的接口,并且负责具体状态的切换

image-20230615200046901

二. 状态模式实例

二.一 抽象状态角色 State

public abstract class State {
    /**
      减少积分
     */
    public abstract  void deductScore();
    /**
     是否抽中奖品
     */
    public abstract  boolean raffle();
    /**
    获取奖品
     */
    public abstract  void sendPrize();

}

二.二 具体状态角色实现

有 不能抽奖, 可以抽奖, 获取礼品, 礼品发送完活动结束 四个状态

二.二.一 不能抽奖 NoChouState

@Slf4j
public class NoChouState extends State{
    private ActivityContext activityContext;

    public NoChouState(ActivityContext activityContext) {
        this.activityContext = activityContext;
    }

    @Override
    public void deductScore() {
       log.info(">>> 扣除积分成功");
       activityContext.setState(activityContext.getCanChouState());
    }

    @Override
    public boolean raffle() {
        log.info(">>> 扣了积分才能抽");
        return false;
    }

    @Override
    public void sendPrize() {
        log.info(">>> 未抽奖,不发放奖品");
    }
}

二.二.二 可以抽奖 CanChouState

@Slf4j
public class CanChouState extends State{
    private ActivityContext activityContext;

    public CanChouState (ActivityContext activityContext) {
        this.activityContext = activityContext;
    }

    @Override
    public void deductScore() {
       log.info(">>> 不能调用扣取积分方法");
    }

    @Override
    public boolean raffle() {

        // 生成一个随机数
        int randNum = new Random().nextInt(3);
        if (randNum == 0) {
            //改变状态
            activityContext.setState(activityContext.getSendState());
            return true;
        }else {
            activityContext.setState(activityContext.getNoChouState());
            return false;
        }
    }

    @Override
    public void sendPrize() {
        log.info(">>> 没有中奖,不发放奖品");
    }
}

二.二.三 抽中,获取奖品 SendState

@Slf4j
public class SendState extends State{
    private ActivityContext activityContext;

    public SendState(ActivityContext activityContext) {
        this.activityContext = activityContext;
    }

    @Override
    public void deductScore() {
       log.info(">>> 不扣除积分");
    }

    @Override
    public boolean raffle() {

        log.info("抽过奖了");
        return false;
    }

    @Override
    public void sendPrize() {
        if (activityContext.getCount() >0) {
            log.info("中奖了");
            activityContext.setCount(activityContext.getCount()-1);
            activityContext.setState(activityContext.getNoChouState());
        } else {
            log.info(">>> 抽奖活动结束了");
            activityContext.setState(activityContext.getSendOutState());
        }
    }
}

二.二.四 奖品发完了,活动结束 SendOutState

@Slf4j
public class SendOutState extends State{
    private ActivityContext activityContext;

    public SendOutState(ActivityContext activityContext) {
        this.activityContext = activityContext;
    }

    @Override
    public void deductScore() {
       log.info(">>> 奖品发送完了,请下次参加");
    }

    @Override
    public boolean raffle() {

        log.info(">>> 奖品发送完了,请下次参加");
        return false;
    }

    @Override
    public void sendPrize() {
        log.info(">>> 奖品发送完了,请下次参加");
    }
}

二.三 环境角色 ActivityContext

@Data
public class ActivityContext {
    private State state;
    private int count;
    // 构建这四个状态
    private State noChouState = new NoChouState(this);
    private State canChouState = new CanChouState(this);

    private State sendState = new SendState(this);
    private State sendOutState = new SendOutState(this);


    public ActivityContext(int count) {
        this.state = noChouState;
        this.count = count;
    }

    public void deductScore() {
       this.state.deductScore();
    }

    public void raffle() {
        if (this.state.raffle()){
            this.state.sendPrize();
        }
    }
}

二.四 客户端调用

10 个用户, 抽3个奖品

/**
     * 状态有: 不能抽奖,能抽奖
     *
     * 状态运转是:
     *
     * 不能抽奖--- > 能提奖---> 抽中了 (不能提奖 /活动结束了)
     */

    @Test
    public void oneTest() {
        ActivityContext activityContext = new ActivityContext(3);

        for (int i = 0; i < 10; i++) {
            log.info(">>> 第 {} 次抽奖", i + 1);
            activityContext.deductScore();
            // 抽奖
            activityContext.raffle();
        }
    }

image-20230615200627387


本章节的代码放置在 github 上:


https://github.com/yuejianli/DesignPattern/tree/develop/State


谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/652123.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

go常用特性(embed、插件化开发)、常用包(并发)

go常用特性及常用包 1 常用特性 1.1 go:build //go:build !windows //go:build是前缀指令&#xff0c;!windows是逻辑判断的条件。这个指令的作用是在Windows系统外&#xff0c;编译当前源文件。// build !windows // build是前缀指令&#xff0c;!windows是编译标记。这个指…

CSDN如何获得铁粉?

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

springboot+vue的校园疫情防控系统(附数据库,源码)

&#x1f495;&#x1f495;作者&#xff1a;程序员徐师兄 个人简介&#xff1a;7 年大厂程序员经历&#xff0c;擅长Java、微信小程序、Python、Android等&#xff0c;大家有这一块的问题可以一起交流&#xff01; 各类成品java毕设 。javaweb&#xff0c;ssh&#xff0c;ssm&…

责任链模式(二十六)

相信自己&#xff0c;请一定要相信自己 上一章简单介绍了策略模式(二十五), 如果没有看过, 请观看上一章 一. 责任链模式 引用 菜鸟教程里面的责任链模式介绍: https://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html 顾名思义&#xff0c;责任链模式…

Science Advance||个体动态脑中鲁棒的大脑状态

文章目录 个体化动态方法&#xff08;INSCAPE 方法&#xff09;&#xff1a;&#xff08;A&#xff09;生成脑共同激活状态的组模板&#xff1a;&#xff08;B&#xff09;个体水平分析&#xff1a; 不同的大脑状态有特定的协同激活模式&#xff08;coactivation patterns&…

ai写作怎么搞?我来教你几招

在当今信息化时代&#xff0c;ai技术的发展已经进入到了一个全新的阶段&#xff0c;越来越多的人们开始运用ai技术进行写作。作为一种创新性的工具&#xff0c;ai写作已经成为了许多企业和个人写作必不可少的工具之一。但是&#xff0c;对于初学者来说&#xff0c;如何快速上手…

【网络技术】NAT是什么?它的工作原理是什么?

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、NAT是什么&#xff1f; 二、NAT的实现方式&#xff08;三种&#xff09; 1、静态转换&#xff08;Static Nat&#xff09; 2、动…

css line-height

项目中看到 line-height&#xff1a;1 所以来总结一下 line-height 属性。 line-height 定义 line-height 属性设置行间的距离&#xff08;行高&#xff09;。 line-height 不允许使用负值。 属性可能的值 值描述normal默认。设置合理的行间距。number设置数字&#xff0…

手机技巧:安卓微信 8.0.38 内测版本功能一览

2023年6月14号安卓版本的微信8.0.38又开始内测了&#xff0c;今天就赶紧下载体验一下&#xff0c;下面就来给大家一一介绍&#xff0c;本次安卓微信内测版本功能更新&#xff0c;感兴趣的朋友可以文末下载体验一下&#xff01; 首先看一下官方的更新内容&#xff1a; 本次更新…

【Axure 教程】中继器(基础篇)

一、初识中继器 中继器是 Axure 中一个比较高阶的应用&#xff0c;它可以让我们在纯静态网页中模拟出类似带有后台数据交互的增删改查的效果&#xff0c;虽然它没有真正意义上帮我们存储任何的数据&#xff0c;但是当我们在一次项目体验过程中&#xff0c;它却可以给我们带来更…

字节跳动提出高性能 transformer 推理库,获 IPDPS 2023 最佳论文奖

动手点关注 干货不迷路 字节跳动与英伟达, 加州大学河滨分校联合发表的论文 《ByteTransformer: A High-Performance Transformer Boosted for Variable-Length》在第 37 届 IEEE 国际并行和分布式处理大会&#xff08;IPDPS 2023&#xff09;中&#xff0c;从 396 篇投稿中脱颖…

广东省高校人工智能产教融合院长研讨会召开,校企协同探索AI教育新范式

为深化产教融合、促进校企合作&#xff0c;着力推进人工智能产业和高校人才培养体系相融合&#xff0c;深入探讨校企合作、产教融合与课程建设规划等事宜&#xff0c;2023年6月9日下午&#xff0c;百度飞桨联合广东省计算机学会、华南理工大学计算机科学与工程学院、荔峰科技&a…

这世界好神奇,我们其实并不了解自己的身体

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 卷圈 运营 / SandLiu 卷圈 监制 / 姝琦 文案 / 粒粒 产品统筹 / bobo 场地支持 / 声湃轩北京站 这是一次突发奇想的天马行空&#xff0c;三个人猝不及防地坐下来大开脑洞&#xff0c;从诗词歌赋聊到人生哲学&#xff…

CVPR 2023 | 美团技术团队精选论文解读

本文精选了美团技术团队被CVPR 2023收录的8篇论文进行解读。这些论文既有自监督学习、领域自适应、联邦学习等通用学习范式方面的技术迭代&#xff0c;也涉及目标检测、跟踪、分割、Low-level Vision等典型视觉任务的性能&#xff0c;体现了美团在基础通用技术和垂直领域技术上…

HotSpot虚拟机对象探索与OutOfMemoryError异常

HotSpot虚拟机对象探索与OutOfMemoryError异常 1.HotSpot虚拟机对象探索 1.1对象的创建 不是一直有一个笑话,别人问程序员有没有对象,程序员会说我没有对象,但是我可以new一个出来 这里就可以判断他学过c或者java等语言 在java中对象的创建一般我们都是通过new来创建的,但…

MyBatis01

ORM&#xff1a;对象关系映射 O&#xff08;Object&#xff09;&#xff1a;Java虚拟机中的Java对象 R&#xff08;Relational&#xff09;&#xff1a;关系型数据库 M&#xff08;Mapping&#xff09;&#xff1a;将Java虚拟机中的Java对象映射到数据库表中一行记录&#xff0…

【王道·操作系统】第三章 内存管理

一、内存管理 1.1 内存的基础知识 内存可存放数据&#xff0c;程序执行前需要先放到内存中才能被CPU处理——缓和CPU与硬盘之间的速度矛盾内存地址从0开始&#xff0c;每个地址对应一个存储单元 按字节编址&#xff1a;每个存储单元大小为1字节(B)&#xff0c;即8个二进制位按…

【Spring Cloud系列】- Eureka使用详解

【Spring Cloud系列】- Eureka使用详解 文章目录 【Spring Cloud系列】- Eureka使用详解一、概述二、Eureka简介三、Eureka结构与作用Eureka结构图Eureka采用CS&#xff08;Client/Server,客户端/服务器&#xff09;架构&#xff0c;它包括以下两大组件 四、Eureka集群及与应用…

梁宁:为什么中国没有像 ChatGPT 和 Vision Pro 这样的创新产品?

6 月 10 日&#xff0c;产品战略专家梁宁和图灵联合创始人刘江围绕“ ChatGPT 真需求”主题进行直播对谈。 梁宁&#xff0c;产品战略专家&#xff0c;曾任湖畔大学产品模块学术主任&#xff0c;联想、腾讯高管&#xff0c;CNET集团副总裁。 工作经历横跨 BAT&#xff0c;与美团…

第14届蓝桥杯Scratch(中级)国赛真题解析2023.5.28

第14届蓝桥杯Scratch(中级)国赛真题解析2023.5.28 一:选择题(50分)第 1 题 单选题(10分) 运行以下程序后,角色说出的数是 ( C )。 *选择题严禁使用程序验证,选择题不答或答错都不扣分 A.150 B.200 C.300 D.600第 2 题 单选题(10分) 对以下程序效果描述完全正确的是 …