《JAVA与模式》之状态模式

Unity适配Nintendo Switch平台开发 查看文档、下载SDK,都需要账号登录。 阅读详情

系列文章目录



前言

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。
在这里插入图片描述在阎宏博士的《JAVA与模式》一书中开头是这样描述状态(State)模式的:

状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式。

状态模式允许一个对象在其内部状态改变的时候改变其行为。这个对象看上去就像是改变了它的类一样。


一、状态模式的结构

用一句话来表述,状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式的示意性类图如下所示:
在这里插入图片描述
状态模式所涉及到的角色有:

●  环境(Context)角色,也成上下文:定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。

●  抽象状态(State)角色:定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为。

●  具体状态(ConcreteState)角色:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。

源代码
  环境角色类

复制代码
public class Context {
//持有一个State类型的对象实例
private State state;

public void setState(State state) {
    this.state = state;
}
/**
 * 用户感兴趣的接口方法
 */
public void request(String sampleParameter) {
    //转调state来处理
    state.handle(sampleParameter);
}

}
复制代码
  抽象状态类

复制代码
public interface State {
/**
* 状态对应的处理
*/
public void handle(String sampleParameter);
}
复制代码
  具体状态类

复制代码
public class ConcreteStateA implements State {

@Override
public void handle(String sampleParameter) {
    
    System.out.println("ConcreteStateA handle :" + sampleParameter);
}

}
复制代码
复制代码
public class ConcreteStateB implements State {

@Override
public void handle(String sampleParameter) {
    
    System.out.println("ConcreteStateB handle :" + sampleParameter);
}

}
复制代码
  客户端类

复制代码
public class Client {

public static void main(String[] args){
    //创建状态
    State state = new ConcreteStateB();
    //创建环境
    Context context = new Context();
    //将状态设置到环境中
    context.setState(state);
    //请求
    context.request("test");
}

}
复制代码
  从上面可以看出,环境类Context的行为request()是委派给某一个具体状态类的。通过使用多态性原则,可以动态改变环境类Context的属性State的内容,使其从指向一个具体状态类变换到指向另一个具体状态类,从而使环境类的行为request()由不同的具体状态类来执行。

二、使用场景

考虑一个在线投票系统的应用,要实现控制同一个用户只能投一票,如果一个用户反复投票,而且投票次数超过5次,则判定为恶意刷票,要取消该用户投票的资格,当然同时也要取消他所投的票;如果一个用户的投票次数超过8次,将进入黑名单,禁止再登录和使用系统。

要使用状态模式实现,首先需要把投票过程的各种状态定义出来,根据以上描述大致分为四种状态:正常投票、反复投票、恶意刷票、进入黑名单。然后创建一个投票管理对象(相当于Context)。

系统的结构图如下所示:
在这里插入图片描述
源代码
  抽象状态类

复制代码
public interface VoteState {
/**
* 处理状态对应的行为
* @param user 投票人
* @param voteItem 投票项
* @param voteManager 投票上下文,用来在实现状态对应的功能处理的时候,
* 可以回调上下文的数据
*/
public void vote(String user,String voteItem,VoteManager voteManager);
}
复制代码
  具体状态类——正常投票

复制代码
public class NormalVoteState implements VoteState {

@Override
public void vote(String user, String voteItem, VoteManager voteManager) {
    //正常投票,记录到投票记录中
    voteManager.getMapVote().put(user, voteItem);
    System.out.println("恭喜投票成功");
}

}
复制代码
  具体状态类——重复投票

复制代码
public class RepeatVoteState implements VoteState {

@Override
public void vote(String user, String voteItem, VoteManager voteManager) {
    //重复投票,暂时不做处理
    System.out.println("请不要重复投票");
}

}
复制代码
  具体状态类——恶意刷票

复制代码
public class SpiteVoteState implements VoteState {

@Override
public void vote(String user, String voteItem, VoteManager voteManager) {
    // 恶意投票,取消用户的投票资格,并取消投票记录
    String str = voteManager.getMapVote().get(user);
    if(str != null){
        voteManager.getMapVote().remove(user);
    }
    System.out.println("你有恶意刷屏行为,取消投票资格");
}

}
复制代码
  具体状态类——黑名单

复制代码
public class BlackVoteState implements VoteState {

@Override
public void vote(String user, String voteItem, VoteManager voteManager) {
    //记录黑名单中,禁止登录系统
    System.out.println("进入黑名单,将禁止登录和使用本系统");
}

}
复制代码
  环境类

复制代码
public class VoteManager {
//持有状体处理对象
private VoteState state = null;
//记录用户投票的结果,Map<String,String>对应Map<用户名称,投票的选项>
private Map<String,String> mapVote = new HashMap<String,String>();
//记录用户投票次数,Map<String,Integer>对应Map<用户名称,投票的次数>
private Map<String,Integer> mapVoteCount = new HashMap<String,Integer>();
/**
* 获取用户投票结果的Map
/
public Map<String, String> getMapVote() {
return mapVote;
}
/
*
* 投票
* @param user 投票人
* @param voteItem 投票的选项
*/
public void vote(String user,String voteItem){
//1.为该用户增加投票次数
//从记录中取出该用户已有的投票次数
Integer oldVoteCount = mapVoteCount.get(user);
if(oldVoteCount == null){
oldVoteCount = 0;
}
oldVoteCount += 1;
mapVoteCount.put(user, oldVoteCount);
//2.判断该用户的投票类型,就相当于判断对应的状态
//到底是正常投票、重复投票、恶意投票还是上黑名单的状态
if(oldVoteCount == 1){
state = new NormalVoteState();
}
else if(oldVoteCount > 1 && oldVoteCount < 5){
state = new RepeatVoteState();
}
else if(oldVoteCount >= 5 && oldVoteCount <8){
state = new SpiteVoteState();
}
else if(oldVoteCount > 8){
state = new BlackVoteState();
}
//然后转调状态对象来进行相应的操作
state.vote(user, voteItem, this);
}
}
复制代码
  客户端类

复制代码
public class Client {

public static void main(String[] args) {
    
    VoteManager vm = new VoteManager();
    for(int i=0;i<9;i++){
        vm.vote("u1","A");
    }
}

}
复制代码
  运行结果如下:
在这里插入图片描述
  从上面的示例可以看出,状态的转换基本上都是内部行为,主要在状态模式内部来维护。比如对于投票的人员,任何时候他的操作都是投票,但是投票管理对象的处理却不一定一样,会根据投票的次数来判断状态,然后根据状态去选择不同的处理。

三、认识状态模式

●  状态和行为

所谓对象的状态,通常指的就是对象实例的属性的值;而行为指的就是对象的功能,再具体点说,行为大多可以对应到方法上。

状态模式的功能就是分离状态的行为,通过维护状态的变化,来调用不同状态对应的不同功能。也就是说,状态和行为是相关联的,它们的关系可以描述为:状态决定行为。

由于状态是在运行期被改变的,因此行为也会在运行期根据状态的改变而改变。

●  行为的平行性

注意平行线而不是平等性。所谓平行性指的是各个状态的行为所处的层次是一样的,相互独立的、没有关联的,是根据不同的状态来决定到底走平行线的哪一条。行为是不同的,当然对应的实现也是不同的,相互之间是不可替换的。
  在这里插入图片描述
  而平等性强调的是可替换性,大家是同一行为的不同描述或实现,因此在同一个行为发生的时候,可以根据条件挑选任意一个实现来进行相应的处理。
在这里插入图片描述
大家可能会发现状态模式的结构和策略模式的结构完全一样,但是,它们的目的、实现、本质却是完全不一样的。还有行为之间的特性也是状态模式和策略模式一个很重要的区别,状态模式的行为是平行性的,不可相互替换的;而策略模式的行为是平等性的,是可以相互替换的。

●   环境和状态处理对象

在状态模式中,环境(Context)是持有状态的对象,但是环境(Context)自身并不处理跟状态相关的行为,而是把处理状态的功能委托给了状态对应的状态处理类来处理。

在具体的状态处理类中经常需要获取环境(Context)自身的数据,甚至在必要的时候会回调环境(Context)的方法,因此,通常将环境(Context)自身当作一个参数传递给具体的状态处理类。

客户端一般只和环境(Context)交互。客户端可以用状态对象来配置一个环境(Context),一旦配置完毕,就不再需要和状态对象打交道了。客户端通常不负责运行期间状态的维护,也不负责决定后续到底使用哪一个具体的状态处理对象。

华大HC32F460 TCP Client 实验 阅读详情

相关推荐

Java设计模式Java设计模式之(十二)状态模式(State Pattern)

状态模式属于行为型模式。 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象,类的行为是基于它的状态改变的。 一、状态模式介绍 意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。 主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。 何时使用:代码中包含大量对象状态有关的条件语句。 如何解决:将各种具体的状态类抽象出来。 关键代码:通常命令模式的接口中只有一个方法。而状态模式的接口中有

No8g攻城狮的博客 798

java设计模式---状态模式(State pattern)

java设计模式状态模式(State pattern) 1. 概述 状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化,对于客户端而言,无须关心对象状态的转换以及对象所处的当前状...

渔潭的博客 465

31省环境规制强度数据,含原始数据、测算方法、参考文献,2004-2022,excel版

31省份环境规制强度、工业污染治理完成投资、第二产业增加值,含原始数据、测算方法、参考文献,2004-2022,excel版21世纪以来,传统经济发展方式导致环境问题凸显,如污染排放增加、资源日渐枯竭、生态失衡等,经济发展可持续发展上升为主要矛盾。面对日益恶化的环境质量,中国共产党第十八届五中全会提出“绿色发展”的核心理念,强调走绿色生产和绿色治理相结合的生态文明之路。如今,环境规制不仅要满足广大人民群众对绿水青山的需求,还应为我国经济发展提供一份助力,为经济健康有序发展保驾护航。实现绿色治理,改善环境质量的有效途径是实施行政命令型、经济市场型等环境规制政策或措施。而环境规制强度的提高会影响企业生产成本、资本劳动要素投入、生产规模等而对社会就业造成一定冲击。一、时间跨度:2004-2022年二、计算方法参考发表于核心期刊《中国软科学》中刘荣增(2021)、《数量经济技术经济研究》中胡洁(2023)的做法,利用工业污染治理投资完成额占第二产业比重衡量环境规制三、数据来源主要来源于国家统计局,祥见下文数据指标部分介绍四、数据指标附件 各省环境规制

22-Java状态模式 ( State Pattern )

1. 意图允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类2. 主要解决对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为3. 何时使用代码中包含大量对象状态有关的条件语句4. 如何解决将各种具体的状态类抽象出来5. 关键代码通常命令模式的接口中只有一个方法。而状态模式的接口中有一个或者多个方法而且,状态模式的实现类的方法,一般返回值,或者是改变实例变量的值也就是说,状态模式一般和对象的状态有关。实现类的方法有不同的功能,覆盖接口中的方法。

深入Java世界:探索编程之美与技术深度 979

JAVA设计模式状态模式【State Pattern】

一、概述     当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化。状态模式是一种对象行为型模式。 二、适用场景     用于解决系统中复杂对象的多种状态转换以及不同状态下行为的封装问题。简单说就是处理对象的多种状态及其相互转换。

小吕丶Code阶区 3879

java状态模式详解_详解JAVA 设计模式状态模式

状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。介绍意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。何时使用:代码中包含大量...

weixin_33508642的博客 286

Java设计模式——状态模式【State Pattern】

Java设计模式状态模式、State Pattern

scorpio的博客 513

java状态模式理解_轻松掌握Java状态模式

轻松掌握Java状态模式发布于 2020-12-4|复制链接摘记: 定义:在状态模式(State Pattern)中,类的行为是基于它的状态改变的。特点:1、封装了转换规则。2、枚举可能的状态,在枚举状态之前需要确定状态种类。3、将所有某个状态有关的行为放到一个类中,并且可以方便地增加新的状态, ..定义:在状态模式(State Pattern)中,类的行为是基于它的状态改变的。特点:1、封装了...

weixin_34221599的博客 115

Java设计模式——状态模式(STATE PATTERN)

Java设计模式——状态模式(STATE PATTERN) 转载:http://blog.csdn.net/u012401711/article/details/52675873

hackxiaoF的专栏 401

Java 状态模式详解

状态模式是一种通过将对象的状态转换逻辑分布到状态对象中来实现状态转换的设计模式。它将对象的行为对应的状态分离,使得在修改对象状态时,不需要修改对象的行为方法。同时,状态模式可以通过将状态的转换逻辑包含在各个状态类中来简化代码,避免出现大量的条件判断语句,从而提高代码的可读性和可维护性。环境(Context):它定义了客户端所感兴趣的接口,并维护一个当前状态,在具体状态类中实现该接口的各个具体操作。抽象状态(State):它定义了一个接口,用于封装环境对象中不同状态对应的行为。

兴趣是最好的老师,勤能补拙 2448

Spring 源码系列(23): SpringApplication.run() 启动全流程

本文深入解析了SpringApplication.run()的核心流程,通过源码拆解揭示了从启动到容器就绪的完整生命周期。文章重点分析了三个关键阶段:prepareEnvironment的配置加载逻辑(系统属性>环境变量>配置文件)、createApplicationContext的容器类型推断机制(基于classpath判断Web/Reactive/普通应用),以及callRunners的启动后回调特性(按@Order执行初始化任务)。同时澄清了常见误区,如内嵌Tomcat实际在refresh阶段的onR

不才不才不不才的博客 397

Java 并发灵魂拷问:notify/signal 唤醒顺序是规范还是实现?

本文探讨了Java中Object.notify()和Condition.signal()唤醒线程的顺序问题。关键结论如下: Object.notify(): JVM规范未规定唤醒顺序,HotSpot实现虽采用FIFO(从WaitSet头部取线程),但这属于实现细节而非规范要求 由于synchronized是非公平锁,被唤醒线程需重新竞争锁,最终执行顺序无法保证 严禁业务代码依赖该顺序 Condition.signal(): 严格按FIFO顺序唤醒(AQS等待队列头部线程) 是设计约定,业务可合理依赖该特性

weixin_68315058的博客 362

[Java]-微服务面试题

服务降级是服务自我保护的一种方式,或者保护下游服务的一种方式,用于确保服务不会受请求突增影响变得不可用,确保服务不会崩溃。微服务的负载均衡主要使用了一个组件Ribbon,比如,我们在使用feign远程调用的过程中,底层的负载均衡就是。2,我们还在skywalking设置了告警规则,特别是在项目上线以后,如果报错,我们分别设置了可以给相关负责人。简历上写的微服务,只要是发生了多个服务之间的写操作,都需要进行分布式事务控制。2,在客户端的配置文件中,可以配置某一个服务调用的负载均衡策略(局部)

. 612

49. 【Java】JDK 21的虚拟线程(上):革命性的并发模型

本文深入解析JDK 21引入的虚拟线程(Virtual Threads)技术,从传统平台线程的资源瓶颈出发,阐述虚拟线程的轻量级特性、M:N调度模型及其工作原理。详细介绍了两种创建虚拟线程的方法,并通过性能对比实验展示其在I/O密集型场景下的显著优势。总结了虚拟线程的适用场景、使用注意事项以及平台线程的核心差异,帮助开发者掌握这一革命性的并发编程工具。

gugucoding的博客 527

Java Spring 批量修改,实体、接口、方法的定义

本文描述了一个批量更新车辆类型的接口实现。该功能通过Controller层接收包含出库单ID列表和车辆类型的请求参数,调用Service层进行处理。实现层采用事务管理,首先验证参数有效性,然后查询对应出库单数据并批量更新车辆类型字段,最后返回操作结果(成功更新记录数或错误信息)。该接口主要用于快递业务中其他出库单的车辆类型批量修改操作,包含完整的参数校验、异常处理和事务管理机制。

LYBWWP 49

简单聊聊 OpenFeign 框架源码

骨架:JDK 动态代理 + 方法元数据 + handler 分发,和 MyBatis 同一套路;主线:调用 → 填 RequestTemplate → 拦截器 → 负载均衡选实例 → Client 执行 → Decoder 解码,异常走 ErrorDecoder/Retryer/fallback;Spring 整合三件事扫描注册 FactoryBean、懒构建代理、给每个客户端独立配置;面试主线。

weixin_47626220的博客 381

并发 13 · 异步编排

摘要:本文探讨了异步编排在秒杀下单场景中的应用,分析了传统Future的局限性,并介绍了CompletableFuture如何通过链式调用解决任务依赖并行问题。文章详细讲解了创建异步任务、串联任务(thenApply/thenCompose)、合并任务(thenCombine/allOf)以及异常处理等核心方法,强调使用独立线程池避免阻塞公共资源。最后结合秒杀案例,展示了如何构建高效、清晰的异步流水线,优化响应时间。全文提供代码示例和选型建议,帮助开发者实现高性能异步流程编排。

记录后端技术的深水区:MySQL、并发、JVM、分布式。原理为主,实战为辅,能少踩一个坑是一个。 403

Spring配置文件

本文系统介绍了配置文件的作用、Spring Boot支持的配置文件格式及其特点。首先阐述了配置文件解决硬编码问题、实现程序灵活配置的核心价值,并以手机字体大小为例说明其应用场景。接着详细讲解了Spring Boot支持的三种配置文件格式(.properties、.yml、.yaml),包括它们的加载优先级和共存规则。最后分别深入分析了properties配置文件的键值对语法、@Value注解读取方式及其冗余信息缺点,以及yml配置文件的基本语法、引号使用规则和优缺点对比,为开发者选择合适的配置文件格式提供参

qq_71356343的博客 246

LangChain4J

Prompt:好比UI层,进行用户交互Langchain4j, Spring AI:好比Controller,调用AI大模型各类AI大模型:好比Service,提供人工智能服务向量数据库:好比Mapper,进行数据存储。

渔阳的博客 188

Spring Boot 实现数据脱敏:自定义注解 + Jackson 序列化器

加了它之后,@Sensitive 就等价于 @JsonSerialize(using = SensitiveJsonSerializer.class) ,Jackson才能识别并触发我们的序列化器。Jackson默认不认识我们自定义的 @Sensitive 注解,@JacksonAnnotationsInside 的作用是:允许把 @JsonSerialize 组合进自定义注解。时,数据库里存的一直是完整值,脱敏是一个展示的动作,而存储层要保护数据应该使用。的这一层比较好,下面是具体实现。

sjkflw121150的博客 210
上一篇: 《JAVA与模式》之访问者模式
下一篇: 《JAVA与模式》之备忘录模式
Java毕设王
博客等级 码龄7年 9146粉丝 942原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java毕设王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值