设计模式(十五)状态模式

相关文章

设计模式系列

前言

建议在阅读本文前先阅读设计模式(十一)策略模式这篇文章,虽说状态模式和策略模式的结构几乎是相同的,但是它们所解决的问题是不同的,读完这两篇文章你就会有了答案。

1.状态模式定义

状态模式定义

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

状态模式UML图

在享元模式中有如下角色:

  • Context:环境角色,定义客户端需要的接口,并且负责具体状态的切换。
  • State:抽象状态角色,可以是抽象类或者接口,负责对象状态定义,并封装了环境角色。
  • ConcreteState:具体状态角色,实现抽象角色类,定义了本状态所要做的事情。

2.简单实现状态模式

拿用mp3听歌来说,mp3有四种基本状态,分别是开机、关机、上一首歌和下一首歌。如果我们要写一个对mp3进行控制的类,你可能会这样写,如下所示。

public class Mp3Controller {
    private static final int POWER_ON = 1;
    private static final int POWER_OFF = 2;
    private int state = POWER_OFF;
    public void powerOn() {
        if (state == POWER_OFF) {
            System.out.println("开机");
        }
        state = POWER_ON;
    }
    public void powerOff() {
        if (state == POWER_ON) {
            System.out.println("关机");
        }
        state = POWER_OFF;
    }
    public void preSong() {
        if (state == POWER_ON) {
            System.out.println("上一首歌");
        }
    }
    public void nextSong() {
        if (state == POWER_ON) {
            System.out.println("下一首歌");
        }
    }
}

在powerOn和powerOff方法中我们会将state置为相应的状态,在preSong和nextSong方法中,首先要判断当前mp3的state,如果是POWER_OFF,则不做任何处理,写到这里你可能会觉得实现很简单啊。那么我再添加些状态,比如待机状态、休眠状态、亮屏状态等等,顺便再添加些功能,比如调大音量、调小音量、降噪等。这样你实现起来,就会发现你会定义很多种状态,在功能中可能要用到多个条件语句进行判断,这会使得代码变得臃肿。

状态模式就是为了解决这一问题,将多个条件语句去掉,使得代码更加清晰,下面来进行实现。

抽象状态角色

public interface Mp3State {
    //开机
    public void powerOn();
    //关机
    public void powerOff();
    //上一首歌曲
    public void preSong();
    //下一首歌曲
    public void nextSong();
}

接口Mp3State中定义了四种功能,接下来我们来实现Mp3State。

具体状态角色

我们先来实现开机状态,代码如下所示。

public class PowerOnState implements Mp3State {
    @Override
    public void powerOn() {
        System.out.println("已开机");
    }
    @Override
    public void powerOff() {
        System.out.println("关机");
    }
    @Override
    public void preSong() {
        System.out.println("上一首歌");
    }
    @Override
    public void nextSong() {
        System.out.println("下一首歌");
    }
}

比较特殊的是powerOn方法中,打印了“已开机”,因为在PowerOnState 状态下进行开机操作是多此一举的。

接着实现关机状态:

public class PowerOffState implements Mp3State {
    @Override
    public void powerOn() {
        System.out.println("开机");
    }
    @Override
    public void powerOff() {
    }
    @Override
    public void preSong() {
    }
    @Override
    public void nextSong() {
    }
}

在关机状态中只实现了powerOn方法,其他的方法都是空实现。

环境角色

public class Context {
    private Mp3State mp3State;
    public void setMp3State(Mp3State mp3State){
        this.mp3State=mp3State;
    }
    public void powerOn(){
        mp3State.powerOn();
        setMp3State(new PowerOnState());
    }
    public void powerOff(){
        mp3State.powerOff();
        setMp3State(new PowerOffState());
    }
    public void preSong(){
        mp3State.preSong();
    }
    public void nextSong(){
        mp3State.nextSong();
    }
}

Context 中定义了setMp3State方法,用来设定状态,其中powerOn方法中会调用setMp3State方法将状态置为PowerOffState,同理powerOff中将状态置为PowerOffState。

客户端调用

public class Client {
    public static void main(String[] args){
        Context context=new Context();
        context.setMp3State(new PowerOffState());
        context.preSong();
        context.powerOn();
        context.nextSong();
        context.powerOff();
    }
}

我们只需要先设定mp3的初始状态,就可以调用各种功能方法了,不需要再考虑功能和状态之间的关系。输出结果为:

开机

下一首歌

关机

虽然这个例子的代码很简单,这里还是给出UML图,如下所示。

3.状态模式的使用场景和优缺点

优点

  • 避免了过多的条件语句,使得结构更清晰,提高代码的可维护性。
  • 每个状态都是一个子类,方便增加和修改状态。
  • 状态被放置到类的内部,外部调用不需要知道类的内部如何实现状态和行为的变换。

缺点

  • 完全使用状态模式,可能会导致子类会过多。

使用场景

  • 代码中包含大量与对象状态有关的条件语句。
  • 对象的行为依赖着状态,并且行为随着状态的改变而改变。

github源码

参考资料

《大话设计模式》

《设计模式之禅》

《Android源码设计模式》



欢迎关注我的微信公众号,第一时间获得博客更新提醒,以及更多成体系的Android相关原创技术干货。

扫一扫下方二维码或者长按识别二维码,即可关注。

时间: 2024-07-31 20:42:12

设计模式(十五)状态模式的相关文章

设计模式十之状态模式1

状态模式,允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类. 这个模式将状态封装成为独立的类,并将动作委托到代表当前状态的对象,我们知道行为会随着内部状态而改变.糖果机提供了一个很好地例子:当糖果机是在NoQuarterState或HasQuarterState两种不同的状态时,你投入25分钱,就会得到不同的行为(机器接受25分钱和机器拒绝25分钱). 如果说你使用的对象能够完全改变它的行为,那么会觉得,这个对象实际上是从别的类实例化而来的.然而,实际上,我们是在使用组合通过简单

设计模式 ( 十五 ) 中介者模式Mediator(对象行为型)

设计模式 ( 十五 ) 中介者模式Mediator(对象行为型) 1.概述 在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责,即将行为分布到各个对象中. 对于一个模块或者系统,可能由很多对象构成,而且这些对象之间可能存在相互的引用,在最坏的情况下,每一个对象都知道其他所有的对象,这无疑复杂化了对象之间的联系.虽然将一个系统分割成许多对象通常可以增强可复用性,但是对象间相互连接的激增又会降低其可复用性,大量的相互连接使得一个对象似乎不太可能

设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕该功能.如查找.排序等,一种经常使用的方法是硬编码(Hard Coding)在一个类中,如须要提供多种查找算法,能够将这些算法写到一个类中,在该类中提供多个方法,每个方法相应一个详细的查找算法:当然也能够将这些查找算法封装在一个统一的方法中,通过if-else-或者case等条件推断语句来进行选择.

【转】设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查找.排序等,一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法:当然也可以将这些查找算法封装在一个统一的方法中,通过if-else-或者case等条件判断语句来进行选择.这

【游戏设计模式】之三 状态模式、有限状态机 & Unity版本实现

本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://blog.csdn.net/poem_qianmo/article/details/52824776 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 游戏开发过程中,各种游戏状态的切换无处不在.但很多时候,简单粗暴的if else加标志位的方式并不能很地道地解决状态复杂变换的问题,这时,就可以运用到状态模式以及状态机来高效地完成任务.状态模式与状态机,因为他们关联紧密,常

设计模式学习之-状态模式

一.状态模式状态模式,当一个对象的内在状态发生改变时允许改变其行为行为,这个对象像是改变了其子类.状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况.把状态的判断逻辑转移到表示不同的状态的一系列类当中,可以把复杂的判断逻辑简化.当然,如果这个状态判断比较简单,那就没有必要用“状态模式”了.这段话有点难以理解,简而言之就是,在一类中根据当前状态去实例化下一状态子类.下面是状态模式结构图. State类,是一个抽象状态类,定义一个接口以封装与Context的特定状态相关的行为.

设计模式<五>——状态模式

类图 状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类[DP].主要解决的就是当控制一个状态的条件表达式过于复杂的时候,把状态转移到表示不同状态的一系列类当中.目的是把复杂而冗长的条件判断简化.好处便是将与特性状态相关的行为局部化,并且将不同状态的行为分割开来.

javascript设计模式学习之十六——状态模式

状态模式的关键是区分事务内部和外部的状态,事务内部状态改变往往会带来事务的行为改变. 状态模式中有意思的一点是,一般我们谈到封装,都是优先封装对象的行为,而非对象的状态.但在状态模式中刚好相反,状态模式的关键是把事务的每种状态都封装为单独的类,跟此种状态有关的行为都封装在这个类的内部.与此同时,我们还可以把状态的切换规则实现分布在状态类中,这样就有效消除了原本存在的大量条件分支语句.

设计模式笔记:状态模式&策略模式

这几天一直在忙期末考和实训,写笔记的时间也没有多少,不说废话了: 这文主要写两种模式:状态跟策略,主要是因为他们的类图一样,并且比较简单,写在同一篇文章里面容易甄别 状态模式:允许对象在内部状态改变时改变他的行为,对象看起来好像修改了他的类 先保留概念的意思,在平常的编程中,如果需要不同的状态,很一般的做法是在你要操作的类里面定义不同的常量代表不同的状态,然后if-else依据不同的状态有不同的实现: 1.你可以想象大量的if-else语句造成的低可读性和低效率 2.其次是你修改这个类的时候很麻

《Java设计模式》之状态模式

状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式. 状态模式允许一个对象在其内部状态改变的时候改变其行为.这个对象看上去就像是改变了它的类一样. 定义与结构 GOF<设计模式>中给状态模式下的定义为:允许一个对象在其内部状态改变时改变它的行为.这个对象看起来似乎修改了它的类.看起来,状态模式好像是神通广大--居然能够"修改自身的类"! 能够让程序根据不同的外部情况来做出不同的响应,最直接的方法就是在程序中将这