大话设计模式学习笔记(16)——状态模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/q1052196521/article/details/79697007

源码git地址 https://github.com/dlovetco/designMode

问题提出

人一生有很多个时期,而不同的时期应该做不同的事情。比如童年需要开心的玩耍,青年需要认真工作,老年可以享受天伦之乐。。。用代码实现上述场景。

使用switch实现

package statemode;

public class StateMode {
    public static void main(String[] args) {
        Life life = new Life();
        life.setPeriod("童年");
        life.doThings();
        life.setPeriod("青年");
        life.doThings();
        life.setPeriod("老年");
        life.doThings();
    }
}

class Life {
    public String getPeriod() {
        return period;
    }

    public void setPeriod(String period) {
        this.period = period;
    }

    private String period;//不同的时期

    public void doThings() {
        switch (period) {
            case "童年":
                System.out.println("玩耍");
                break;
            case "青年":
                System.out.println("工作");
                break;
            case "老年":
                System.out.println("享受天伦之乐");
                break;
        }
    }
}

虽然说我们确实已经实现题目要求的场景了,但是大家也能看出很多的问题在其中。
1. 若题目中给的状态很多,那么doThings()方法的switch判断会变得很长(如果使用if-else则会更加长)
2. 如果要新增状态,则需要修改原来的方法。违背了开放封闭原则

根据我们一贯的方式,往往都是增加类的结构层次来把switch逻辑拆开来。于是有了下面的状态模式

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

package statemode;

public class StateMode {
    public static void main(String[] args) {
        Life life = new Life();
        life.setPeriod("青年");
        life.doThings();
    }
}

interface State {
    void doThings(Life life);
}

class Life {
    private String period;

    private State state = new Childhood();//初始化是童年

    public void doThings() {
        state.doThings(this);
    }

    public String getPeriod() {
        return period;
    }

    public void setPeriod(String period) {
        this.period = period;
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }
}

class Childhood implements State {

    @Override
    public void doThings(Life life) {
        //是童年就玩耍 否则自动转入青年
        if ("童年".equals(life.getPeriod())) {
            System.out.println("玩耍");
        } else {
            life.setPeriod("青年");
            life.setState(new Youth());
            life.doThings();
        }
    }
}

class Youth implements State {

    @Override
    public void doThings(Life life) {
        if ("青年".equals(life.getPeriod())) {
            System.out.println("工作");
        } else {
            life.setPeriod("老年");
            life.setState(new Elder());
            life.doThings();
        }
    }
}

class Elder implements State {

    @Override
    public void doThings(Life life) {
        if ("老年".equals(life.getPeriod())) {
            System.out.println("享受天伦之乐");
        }
    }
}

输出: 工作
这里先定义了一个State接口,用于表示每个时期要做什么事情。而具体是什么时期,需要另外一个Life类传入参数。童年,青年,老年三个时期分别实现State接口,实现自己不同的doThings()方法。Life类中保存了State的引用和一个period字段表示当前是什么时期。而在Life中的doThings()方法则使用代理的思想,调用State的doThings()方法,这样子的话客户端就不需要知道State的存在,只需要跟Life打交道。此外还有一点,在State的诸多实现类中,如Childhood。它在判断Life传进来的period字段的时候,如果不符合则会自动改变life的状态到青年,再一次调用life.doThings()。由于代理的机制,相当于再一次调用Youth的doThings()。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。状态模式通过把各种状态转移逻辑分不到State的子类中间,减少了相互之间的依赖

plantuml

@startuml
interface State{
{abstract}doThings(Life life)
}
State <|.. Childhood
class Childhood{
doThings(Life life)
}
State <|.. Youth
class Youth{
doThings(Life life)
}
State <|.. Elder
class Elder{
doThings(Life life)
}

State <..* Life
class Life{
String period
State state
}
@enduml

这里写图片描述

猜你喜欢

转载自blog.csdn.net/q1052196521/article/details/79697007
今日推荐