您当前的位置: 首页 > 

Dongguo丶

暂无认证

  • 3浏览

    0关注

    472博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

设计模式之状态模式

Dongguo丶 发布时间:2019-01-14 00:05:39 ,浏览量:3

.

模式定义

​ 在很多情况下,一个对象的行为取决于它的一个或多个变化的属性,这些属性我们称之为状态,这个对象称之为状态对象。对于状态对象而已,它的行为依赖于它的状态,比如你要预订房间,那么只有当该房间为空闲时你才能预订,你想入住该房间也只有当你预订了该房间或者该房间为空闲时。对于这样的一个对象,当它在于外部事件产生互动的时候,其内部状态就会发生改变,从而使得他的行为也随之发生改变。

​ 那么何为状态模式呢?所谓状态模式就是允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。

结构

 

模式的组成

环境类(Context):  定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。 抽象状态类(State):  定义一个接口以封装与Context的一个特定状态相关的行为。 具体状态类(ConcreteState):  每一子类实现一个与Context的一个状态相关的行为。

在平常开发自己也会遇到好多方法过长,里面的判断语句太多,导致后续修改十分麻烦。今天看到状态模式的介绍,觉得很受益。举个吃饭的例子,下面通过一段没有使用状态模式的代码

public class Person {
    private int hour;
 
    public int getHour() {
        return hour;
    }
 
    public void setHour(int hour) {
        this.hour = hour;
    }
    public void doSonmething(){
        if (hour == 7){
            System.out.println("吃早餐");
        }else if (hour == 12){
            System.out.println("吃午餐");
        }else if (hour == 18){
            System.out.println("吃餐晚");
        }
    }
}
从上述代码中看出,当我要修改hour的判断范围,或者在各个判断条件之后新增一些功能,都会使这段方法变得十分长,而且阅读起来也比较繁琐。
所以代码过长了就有坏味道了。在面向对象的设计中也希望做到代码的责任分解。

当一个对象状态转换的条件表达式过于复杂的时候,把状态的判断逻辑移到不同的一系列类当中,可以把复杂的判断逻辑简单化,这就是状态模式的主要作用。但并不是所有有判断的都要使用状态模式,简单的判断逻辑就不需要了。

代码改良

public class Person {
    private int hour;
    private State state;
 
    public Person() {
 
        state = new  MState();
    }
 
    public int getHour() {
        return hour;
    }
 
    public void setHour(int hour) {
        this.hour = hour;
    }
    public void doSonmething(){
        state.doSomething(this);
    }
 
    public State getState() {
        return state;
    }
 
    public void setState(State state) {
        this.state = state;
    }
}
public abstract class State {
    public abstract void doSomething();
}
public class MState extends State{
    @Override
    public void doSomething(Person person) {
        if (person.getHour() == 7){
            System.out.println("吃早饭");
        }else {
            person.setState(new LState());
            person.doSonmething();
        }
 
    }
}
public class LState extends State {
    @Override
    public void doSomething(Person person) {
        if (person.getHour() == 12){
            System.out.println("吃午饭");
        }else {
            person.setState(new SState());
            person.doSonmething();
        }
    }
}
public class SState extends State {
    @Override
    public void doSomething(Person person) {
        if (person.getHour() == 18){
            System.out.println("吃晚饭");
        }
    }
}
    public static void main(String[] args) {
        Person person = new Person();
        person.setHour(7);
        person.doSonmething();
 
        person.setHour(18);
        person.doSonmething();
    }
运行结果:

吃早饭

吃晚饭

在客户端代码不需要做任何的修改,程序可以变得非常灵活,当程序还需要添加一个额外的工作状态时,再添加一个其它状态类的代码,也不影响其它状态类的代码。

优点

​ 1、封装了转换规则。 2、枚举可能的状态,在枚举状态之前需要确定状态种类。

​ 3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。

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

缺点

​ 1、状态模式的使用必然会增加系统类和对象的个数。 2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。

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

模式适用场景

​ 1、对象的行为依赖于它的状态(属性)并且可以根据它的状态改变而改变它的相关行为。 2、代码中包含大量与对象状态有关的条件语句

模式总结

​ 1、状态模式允许一个对象基于内部状态而拥有不同的行为。

​ 2、Context会将行为委托给当前状态对象。

​ 3、状态模式对“开闭原则”支持不是很好。

关注
打赏
1638062488
查看更多评论
立即登录/注册

微信扫码登录

0.0363s