状态模式(行为型)

原创 2017年01月03日 14:39:01

  在很多种情况下,一个对象的行为取决于一个或多个动态变化的属性,这些属性称为状态。例如水,液态时可以流动,气态时可以扩散,结冰时成了固态,这时既不能流动也不能扩散。例如使用键盘输入字符,当Caps Lock开启时,处于大写状态,这时输入的是大写字母,当Caps Lock关闭时,输入的是小写字母。例如用手机打电话,有信号并且话费充足时,才可以打电话,当没信号或者是处于欠费状态,就无法打电话了。
  上面的例子都很接近于生活,浅显易懂。如果要对上面的这些逻辑进行编码实现,其实用if…else就可以,但当涉及的状态和行为很多时,这一大坨的代码就会变得很繁杂,维护起来很费力,也不利于扩展,当有新的状态时,就要对原来的代码进行比较大的改动,这时我们就需要考虑使用状态模式来让我们的代码变得更优雅,便于维护,便于扩展。
定义:允许一个对象在其内部状态改变时改变他的行为。
结构

  • Context:环境角色,定义客户端需要的接口,并且负责具体状态的切换
  • State:抽象状态角色,为接口或者抽象类,负责对状态定义,并且封装环境角色以实现状态切换。
  • ConcreteState:具体的状态角色,有两个职责:本状态的行为(本状态下要做的事情,以及本状态如何过渡到其他状态)管理和趋向状态处理;

适用场景

  • 行为随状态改变而改变,行为受状态约束的情况下
  • 条件、分支判断语句的替代者:在程序中大量使用switch或者if判断语句导致程序结构不清晰,逻辑混乱,使用状态模式可以很好地避免这一问题,通过扩展子类实现条件的判断处理

UML
这里写图片描述

下面就是状态模式的代码实现,这里以手机在有无话费状态下打电话为例子:
Context:本例中即为Class Phone

public class Phone {
    private State hasPhoneCharge;
    private State phoneArrears;
    private State nowState;
    //初始状态,该手机还剩下1块钱话费
    private int phoneBill=1;
    public State getHasPhoneCharge() {
        return hasPhoneCharge;
    }
    public Phone setHasPhoneCharge(State hasPhoneCharge) {
        this.hasPhoneCharge = hasPhoneCharge;
        return this;
    }
    public State getPhoneArrears() {
        return phoneArrears;
    }
    public Phone setPhoneArrears(State phoneArrears) {
        this.phoneArrears = phoneArrears;
        return this;
    }
    public State getNowState() {
        return nowState;
    }
    public Phone setNowState(State nowState) {
        this.nowState = nowState;
        return this;
    }
    public int getPhoneBill() {
        return phoneBill;
    }
    public Phone setPhoneBill(int phoneBill) {
        this.phoneBill = phoneBill;
        return this;
    }
    public void call(){
        nowState.call();
    }
    public void payPhoneBill(int bill){
        nowState.payPhoneBill(bill);
    }
}

State

public interface State {
    void call();
    void payPhoneBill(int bill);
}

ConcreteState

public class PhoneArrears implements State{
    Phone phone;
    public PhoneArrears(Phone phone){
        this.phone = phone;
    }
    @Override
    public void call() {
        System.out.println("您的手机已停机,无法拨打电话");
    }
    @Override
    public void payPhoneBill(int bill) {
        phone.setPhoneBill(phone.getPhoneBill()+bill);
        System.out.println("成功充值"+bill+"元,目前话费余额"+phone.getPhoneBill());
        if(phone.getPhoneBill()>0){
            phone.setNowState(phone.getHasPhoneCharge());
        }
    }
}

public class HasPhoneCharge implements State{
    Phone phone;
    public HasPhoneCharge(Phone phone){
        this.phone = phone;
    }
    @Override
    public void call() {
        System.out.println("通话成功,扣除一元话费");
        phone.setPhoneBill(phone.getPhoneBill()-1);
        if(phone.getPhoneBill()<=0){
            System.out.println("您的手机因话费不足已停机,请充值");
            phone.setNowState(phone.getPhoneArrears());
        }
    }
    @Override
    public void payPhoneBill(int bill) {
        phone.setPhoneBill(phone.getPhoneBill()+bill);
        System.out.println("成功充值"+bill+"元,目前话费余额"+phone.getPhoneBill());
    }
}

Test:运行一下看下打印出的是什么!

public class Test {
    public static void main(String[] args) {
        Phone phone = new Phone();
        //这里不是错误,想偷懒就弄成链式调用了
        phone.setHasPhoneCharge(new HasPhoneCharge(phone))
             .setPhoneArrears(new PhoneArrears(phone))
             .setNowState(phone.getHasPhoneCharge());
        phone.call();
        phone.call();
        phone.payPhoneBill(10);
        phone.call();
    }

}

总结:通过上面的代码我们可以看到,使用状态模式有效的避免被了过多的switch和if判断语句,降低了程序的复杂性,并且提高了可维护性。这样做程序的封装性也显得非常好,状态变换放置到类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的变换。状态模式有一个缺点就是子类太多(这也是大多数设计模式的共同缺点),如果一个事物有很多个状态使用状态模式就会有很多子类,尽管如此,也好过于去看一大坨的if…else语句,至少在逻辑上可以一目了然。


参考:https://github.com/nivance/DPModel/tree/master/src/dp/com/company/state
   https://segmentfault.com/a/1190000003818435
   http://dreamrunner.org/blog/2014/05/04/%E6%B5%85%E8%B0%88%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F13/

版权声明:本文为博主原创文章,未经博主允许不得转载。

设计模式(行为型)之状态模式(State Pattern)

状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式。状态模式将一个对象的状态...
  • yanbober
  • yanbober
  • 2015年05月05日 15:32
  • 3922

行为型设计模式-状态模式

状态模式: 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。 状态模式参与角色: 上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,...
  • yang1464657625
  • yang1464657625
  • 2017年03月02日 11:58
  • 139

行为型之状态模式

适用:对象状态影响行为,在不同状态下行为不同,经常需要改变状态来完成不同行为时,类似于多个if-else语句并列使用或switch语句的适用情况.结构:1、状态接口,规定了“通过改变状态达到改变行为目...
  • explorewen
  • explorewen
  • 2008年08月20日 14:21
  • 282

设计模式--行为型--状态模式

一、状态模式简介(Brief Introduction) 状态模式(State Pattern),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。 二、解决的问题(What...
  • acesql
  • acesql
  • 2012年11月26日 15:59
  • 192

状态模式(行为型)

状态模式(State Pattern) 又称为状态对象模式,该模式允许一个对象在其内部状态改变时改变其行为.设计场景: 你看电视机时需要频繁变更不同频道,如何设计?此时有三个对象: 人Person,...
  • Petershusheng
  • Petershusheng
  • 2016年06月16日 00:08
  • 395

状态模式State(对象行为型)

转自:http://blog.csdn.net/hguisu/article/details/7557252 1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理...
  • song_hui_xiang
  • song_hui_xiang
  • 2016年02月17日 10:40
  • 817

设计模式(十七)—状态模式(行为型)

一、简介(Brief Introduction)      当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况...
  • gxq741718618
  • gxq741718618
  • 2013年04月22日 21:54
  • 589

二十、状态模式State(行为型)

允许一个对象在其内部状态改变时改变它的行为,这种改变看起来似乎是修改了它的类本身。就像进行TCP连接时,TCP连接的状态都会经过一系列的变化,当从一个状态变为另一个状态时,它的功能就可能发生变化。...
  • teaandnoodle
  • teaandnoodle
  • 2016年07月30日 22:00
  • 194

Java设计模式_(行为型)_状态模式

引用百科 (源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断...
  • vtopqx
  • vtopqx
  • 2017年10月13日 11:02
  • 19988

设计模式-行为型- 状态模式(State)

设计模式-行为型- 状态模式(State) 定义:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类...
  • jx_870915876
  • jx_870915876
  • 2016年08月16日 19:12
  • 19373
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:状态模式(行为型)
举报原因:
原因补充:

(最多只允许输入30个字)