千家信息网

如何理解Java设计模式的状态模式

发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,本篇内容介绍了"如何理解Java设计模式的状态模式"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、
千家信息网最后更新 2025年01月19日如何理解Java设计模式的状态模式

本篇内容介绍了"如何理解Java设计模式的状态模式"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

一、什么是状态模式

定义:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

主要解决:当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。

意图:允许一个对象在其内部状态改变时改变它的行为

二、状态模式的结构

在该类图中,我们看到三个角色:

(1)Context: 环境类,定义客户感兴趣的接口,维护一个State子类的实例,这个实例对应的是对象当前的状态。

(2)State:抽象状态类或者状态接口,定义一个或者一组行为接口,表示该状态下的行为动作。

(3)ConcreteState: 具体状态类,实现State抽象类中定义的接口方法,从而达到不同状态下的不同行为。

三、状态模式的使用场景

1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。

2.一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。

例子:我们在微博上看到一篇文章,觉得还不错,于是想评论或者转发,但如果用户没有登录,这个时候就会先自动跳转到登录注册界面,如果已经登录,当然就可以直接评论或者转发了。这里我们可以看到,我们用户的行为是由当前是否登录这个状态来决定的,这就是典型的状态模式情景。

当然还包括很多其他动作,例如转发、分享、打赏等等,都要重复判断状态才行,如果程序随着需求的改动或者功能逻辑的增加需要修改代码,那么你只要遗漏了一个判断,就会出问题。

而使用状态模式,可以很好地避免过多的if-else -分支,状态模式将每一个状态分支放入一个独立的类中,每一个状态对象都可以独立存在,程序根据不同的状态使用不同的状态对象来实现功能。

四、状态模式和策略模式对比

如果我们在编写代码的时候,遇到大量的条件判断的时候,可能会采用策略模式来优化结构,因为这时涉及到策略的选择,但有时候仔细查看下,就会发现,这些所谓的策略其实是对象的不同状态,更加明显的是,对象的某种状态也成为判断的条件。

策略模式的Context含有一个Strategy的引用,将自身的功能委托给Strategy来完成。

我们把Strategy接口改个名字为State,这就是状态模式了,同样Context也有一个State类型的引用,也将自己的部门功能委托给State来完成。

要使用状态模式,我们必须明确两个东西:状态和每个状态下执行的动作。

在状态模式中,因为所有的状态都要执行相应的动作,所以我们可以考虑将状态抽象出来。

状态的抽象一般有两种形式:接口和抽象类。如果所有的状态都有共同的数据域,可以使用抽象类,但如果只是单纯的执行动作,就可以使用接口。

他们之间真正的区别在策略模式对Strategy的具体实现类有绝对的控制权,即Context要感知Strategy具体类型。而状态模式,Context不感知State的具体实现,Context只需调用自己的方法,这个调用的方法会委托给State来完成,State会在相应的方法调用时,自动为Context设置状态,而这个过程对Context来说是透明的,不被感知的。

五、状态模式的优缺点

优点:

1、封装了转换规则。

2、枚举可能的状态,在枚举状态之前需要确定状态种类。

3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。

4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。

5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点:

1、状态模式的使用必然会增加系统类和对象的个数。

2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。

3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

六、状态模式的实现

抽象状态类,定义一个接口以封装与Context类(Work)的一个特定状态相关的行为。

public abstract class State{    public abstract void WriteProgram(Work w);}

工作状态类,每一个子类实现一个与Context类(Work)的一个状态相关的行为。

//上午工作状态public class ForeNoonState : State{    public override void WriteProgram(Work w)    {        if (w.Hour < 12)        {            Console.WriteLine("当前时间:{0}点,上午工作,精神百倍", w.Hour);        }        else        {            //超过12点,则转入中午工作状态            w.SetState(new NoonState());            w.WriteProgram();        }    }}
//中午工作状态public class NoonState : State{    public override void WriteProgram(Work w)    {        if (w.Hour < 13)        {            Console.WriteLine("当前时间:{0}点,吃午饭,午休", w.Hour);        }        else        {            //超过13点,则转入下午工作状态            w.SetState(new AfterNoonState());            w.WriteProgram();        }    }}
//下午工作状态public class AfterNoonState : State{    public override void WriteProgram(Work w)    {        if (w.Hour < 17)        {            Console.WriteLine("当前时间:{0}点,下午工作,继续努力", w.Hour);        }        else        {            //超过17点,则转入晚上工作状态            w.SetState(new EveningState());            w.WriteProgram();        }    }}
//晚上工作状态public class EveningState : State{    public override void WriteProgram(Work w)    {        if (w.Finish)        {            //如果状态已完成,则转入下班状态            w.SetState(new RestState());            w.WriteProgram();        }        else        {            if (w.Hour < 21)            {                Console.WriteLine("当前时间:{0}点,加班", w.Hour);            }            else            {                //超过21点,则转入睡眠工作状态                w.SetState(new SleepingState());                w.WriteProgram();            }        }    }}
//睡眠工作状态public class SleepingState : State{    public override void WriteProgram(Work w)    {        Console.WriteLine("当前时间:{0}点,睡觉", w.Hour);    }}//下班休息状态public class RestState : State{    public override void WriteProgram(Work w)    {        Console.WriteLine("当前时间:{0}点,下班", w.Hour);    }}

工作类,Context类,维护一个ConcreteState子类(工作状态类)的实例,这个实例定义当前的状态

public class Work{    private State current;    public Work()    {        //工作初始化为上午工作状态        current = new ForeNoonState();    }    //"钟点"属性,状态转换的依据    private double hour;    public double Hour    {        get { return hour; }        set { hour = value; }    }    //"任务完成"属性,是否能下班的依据    private bool finish = false;    public bool Finish    {        get { return finish; }        set { finish = value; }    }     public void SetState(State s)    {        current = s;    }     public void WriteProgram()    {        current.WriteProgram(this);    }}

客户端代码

class Program{    //客户端代码    static void Main(string[] args)    {        Work w = new Work();        w.Hour = 9;        w.WriteProgram();        w.Hour = 10;        w.WriteProgram();        w.Hour = 12;        w.WriteProgram();        w.Hour = 13;        w.WriteProgram();        w.Hour = 14;        w.WriteProgram();        w.Hour = 17;         w.Finish = false;        //w.Finish = true;        w.WriteProgram();        w.Hour = 19;        w.WriteProgram();        w.Hour = 22;        w.WriteProgram();         Console.Read();    }}

结果

当前时间:9点,上午工作,精神百倍
当前时间:10点,上午工作,精神百倍
当前时间:12点,吃午饭,午休
当前时间:13点,下午工作,继续努力
当前时间:14点,下午工作,继续努力
当前时间:17点,加班
当前时间:19点,加班
当前时间:22点,睡觉

"如何理解Java设计模式的状态模式"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

状态 模式 工作 对象 时间 行为 接口 不同 策略 代码 动作 结构 分支 功能 实例 方法 条件 逻辑 登录 复杂 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 手机网络安全手抄报视频 计算机与网络技术基础实训考试题 计算机网络安全防治措施 影视建模渲染服务器租赁费用 数据库表中名字修改 常州运营软件开发优势 高中网络技术基础电子教材 流浪者柯南服务器要买吗 福州软件开发服务 四川系统软件开发需要多少钱 网络安全产品替代 网络安全及保密工作是刂到些 方舟端游的山海经服务器怎么进入 正规的软件开发公司哪家好 ss服务器搭建 计算机网络安全现状及解决方案 数据库如何查询课程表 百度网络安全员工资待遇 mysql数据库查询输出 云平台服务器管理软件 k8s高可用mysql数据库 ip话题谈未来网络技术研究 网络安全管理员考试 网络安全问题普遍出现的时间 数据库附加不成功怎么回事 网络安全 谁管理谁负责 欧瑞博服务器升级需要多久 网络安全口号标语小学生 南京大数据服务器规格 网站的数据库要怎么画ee图
0