设计模式之状态模式

此文介绍我理解的状态设计模式,这是行为模式的一种,在很多需求的场景,一个对象的行为依赖对象的状态,这种场景很多,而且这种状态是可能持续迭代的,这种需求我们一般会给对象一个状态标志然后if-else判断去实现业务逻辑,这样每次来个新的状态都要增加 if-else,这样非常不好维护,需要去修改原来的类,不满足开闭原则。我举个例子,一个人的状态有很多种,穷或则富,或则中产,或则小康。不同的状态做同样的事情的感觉肯定不一样,而且以后可能还会增加新的人的分类。怎么去扩展呢。
按照不用模式的写法,是这样的:

public class Person {

    private String status;

    private String name;

    //setter getter
}

然后一个调用类,各种行为需要判断人的状态:

class StateAction {
    private Person person;
    public StateAction(Person person) {
        this.person = person;
    }

    public void show() {
        // 变化剧烈,不好维护
        if (person.getStatus() == "穷") {
            drive("自行车");
            dress("旧衣服");
            System.out.println("....");
            System.out.println("很穷的各种");
        } else if (person.getStatus() == "富") {
            drive("豪车");
            dress("皮大衣");
            System.out.println("....");
            System.out.println("各种炫富啊");

        } else if (person.getStatus() == "中产") {
            // 如果以后还有各种状态...累死了, Bad smell
            // T A T
        }
        // else if 
    }

    private void drive(String msg) {
        System.out.println(this.person.getName() + "开" + msg);
    }

    private void live(String msg) {
        System.out.println(this.person.getName() + "住" + msg);
    }

    private void dress(String msg) {
        System.out.println(this.person.getName() + "穿" + msg);
    }

}

// 调用方法
        Person person = new Person("小马哥");

        // 不用模式
        person.setStatus("穷");
        StateAction stateAction = new StateAction(person);
        stateAction.show();

        person.setStatus("富");
        stateAction.show();

这个是很正常的思维方式,这样是不好的,添加if else不好维护而且StateAction这个类承担了过多的指责,具体的对象状态与类的行为绑定死了,一旦一个状态的行为改变了,只能去改原先的逻辑,如果能达到一个动态的对象与行为的组合是更灵活的一种方式,把状态与人的行为与分离出来。能够让不同状态的行为变化能够动态的组合。
分析这个场景下的稳定部分与不稳定的部分
稳定的行为:
人的行为,那就是都有drive, dress, live这几个方法
不稳定的部分:
不同状态下的行为不稳定,可能有很多种行为方式集合
以下用状态的模式重写这块:

/**
 * 状态模式,隔离状态的接口
 * 这里描述了具体人的不同的状态
 */
interface State {

    void dress();

    void drive();

    void live();
}
/**
 * 抽象实现,传入person作为状态的上下文
 * Person可以是抽象类,那样是不是就和桥模式非常像,可以动态组装两个维度的变化对象
 * 这里主要演示人在不通状态下的不同行为,所以person为具体实现
 */
abstract class AbstractPersonState implements State {

    protected Person person;

    /**
     * 传入上下文
     * @param person
     */
    public AbstractPersonState(Person person) {
        this.person = person;
    }

    protected String getPersonName() {
        return this.person.getName();
    }

    protected void print(String msg){
        System.out.println(msg);
    }

    /**
     * 展示下生活状态
     */
    public void show() {
        //  钩子方法
        this.drive();
        this.dress();
        this.live();
    }
}

/**
 * 穷人状态
 */
class PoolPersonState extends AbstractPersonState implements State {

    public PoolPersonState(Person person) {
        super(person);
    }

    @Override
    public void dress() {
        print(getPersonName() + "穿旧衣服");
    }

    @Override
    public void drive() {
        print(getPersonName() + "开自行车");
    }

    @Override
    public void live() {
        print(getPersonName() + "住农民房");
    }
}

/**
 * 富豪状态
 */
class RichPersonState extends AbstractPersonState implements State {
    public RichPersonState(Person person) {
        super(person);
    }

    @Override
    public void dress() {
        print(getPersonName() + "穿皮大衣");
    }

    @Override
    public void drive() {
        print(getPersonName() + "开豪车啊");
    }

    @Override
    public void live() {
        print(getPersonName() + "住豪宅啊");
    }
}

        // 调用方式
        PoolPersonState poolPersonState = new PoolPersonState(person);
        poolPersonState.show();

        RichPersonState richPersonState = new RichPersonState(person);
        richPersonState.show();

动态的组合状态和对应的人,使其表现出不同的行为,如果有新的状态行为,只要定义新的AbstractState子类即可,在使用的地方就可以组合以下,而不用修改其他的代码,这样提高了代码的维护性和扩展性,满足了开闭原则并且分离了人与状态。
很多模式都很类似,这里的模式网上有很多文章大谈状态模式与策略模式的区别,因为从另一个角度,状态模式的确与策略模式非常类似,把状态State看成策略接口,再把AbstractPersonState看成环境类,就和策略模式如出一辙,的确,甚至把Person定义成抽象类或接口,也能看到桥模式的影子。策略模式解决的是一系列算法中差异算法的封装,可以看成是从另一个角度看待这个模式,而桥模式是从变化维度的角度来管控变化的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值