设计模式之状态模式(十三)

状态模式

简介

         当一个对象的内在状态改版的时候,允许改变其行为,这个对象看起来像是改变了其类。简单来说就是我们在编程的时候可能会根据对象的状态去写很多的判断语句if else。那么状态模式就是将判断的语句封装到一个对象中,这样对于扩展和改变状态的判断都非常的方便。

类图

实现方式

         汽车我们都知道有油箱,但是对于油箱还有多少的油量这个就是某种状态。对于常规的代码实现要判断油箱的状态是使用if-else语句来实现的。


package com.rabbit.pattern.state;

/**
 * Created by HASEE on 2018/4/5.
 */
public class CarState {

    public void oilState(double l) {
        if (l >= 100) {
            System.out.println("油量充足");
        } else if (l >= 50 && l < 100) {
            System.out.println("油量足够,注意加油");
        } else if (l >= 10 && l < 50) {
            System.out.println("油量比较少");
        } else {
            System.out.println("油量见底了,随时停车");
        }
    }

}
@Test
public void test() {
    CarState cs = new CarState();
    cs.oilState(200D);
    cs.oilState(60D);
    cs.oilState(30D);
    cs.oilState(5D);
}

这样简单的几个状态就需要使用这么长的if-else语句来判断,并且如果新增了其它状态,那么是需要修改这个类的。

如何解决这类问题呢?如果我们将判断的逻辑封装到一个类中,那么就可以轻松的增加判断的逻辑条件了。这其实就是设计模式中的状态模式,就是根据对象的某个状态去处理不同的逻辑。

使用状态模式的代码实现。

package com.rabbit.pattern.state;

/**
 * Created by HASEE on 2018/4/5.
 */
public class Car {

    private String name;//汽车名称
    private double oil;//汽车油量
    private State state;//状态

    public Car(String name, double oil, State state) {
        this.name = name;
        this.oil = oil;
        this.state = state;
    }

    public void nowState() {//判断当前车的油量状态
        state.st(this);
    }

    public void setOil(double oil) {//油量使用就减少,加油就增加,所以提供set方法
        this.oil = oil;
    }

    public String getName() {
        return name;
    }

    public double getOil() {
        return oil;
    }
}

抽象的逻辑类

package com.rabbit.pattern.state;

/**
 * Created by HASEE on 2018/4/5.
 */
public abstract class State {

    //状态
    protected abstract void st(Car c);

}

具体的条件逻辑

package com.rabbit.pattern.state;

/**
 * Created by HASEE on 2018/4/5.
 */
public class State100 extends State {
    @Override
    protected void st(Car c) {
        if (c.getOil() >= 100) {
            System.out.println(c.getName() + "油量充足");
        } else {//当前状态不满足,执行这个状态的下一个状态
            new State50().st(c);
        }
    }
}
package com.rabbit.pattern.state;

/**
 * Created by HASEE on 2018/4/5.
 */
public class State50 extends State {
    @Override
    protected void st(Car c) {
        if (c.getOil() >=50 && c.getOil() < 100) {
            System.out.println(c.getName() + "油量足够,注意加油");
        } else {
            new State10().st(c);
        }
    }
}
package com.rabbit.pattern.state;

/**
 * Created by HASEE on 2018/4/5.
 */
public class State10 extends State {
    @Override
    protected void st(Car c) {
        if (c.getOil() >= 10 && c.getOil() < 50) {
            System.out.println(c.getName() + "油量比较少");
        } else {
            new State0().st(c);
        }
    }
}
package com.rabbit.pattern.state;

/**
 * Created by HASEE on 2018/4/5.
 */
public class State0 extends State {
    @Override
    protected void st(Car c) {
        if (c.getOil() >= 0 && c.getOil() < 10) {
            System.out.println(c.getName() + "油量见底了,随时停车");
        } else {
            System.out.println(c.getName() + "没油了");
        }
    }
}
@Test
public void test1() {
    Car bmw = new Car("BMW", 150, new State100());
    bmw.nowState();
    bmw.setOil(60D);
    bmw.nowState();
    bmw.setOil(20D);
    bmw.nowState();
}

使用了状态模式后,我们将逻辑条件的判断封装到类中,以后需要新增其它逻辑的时候只需要扩展State类,并且修改逻辑顺序即可。

总结

优点

1、封装了转换规则。 2、枚举可能的状态,在枚举状态之前需要确定状态种类。 3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。 5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点

 1、状态模式的使用必然会增加系统类和对象的个数。 2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。 3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

使用场景

1、行为随状态改变而改变的场景。 2、条件、分支语句的代替者。










展开阅读全文
©️2019 CSDN 皮肤主题: Age of Ai 设计师: meimeiellie
应支付0元
点击重新获取
扫码支付

支付成功即可阅读