State模式:摄计魔士和夜芙蓉在暗房双修

摄计魔士大法师不仅炼丹,也练功。他有一种独门法术,修女不修男,需要和弟子在密室成双修炼,以获通灵之神丹。在整个修炼过程中,女弟子将在三种境界中来回切换,分别是:

  • 氣虚態
  • 氣持態
  • 潰散態

而摄计魔士则通过输气、卸气、神击三种法术,来切换弟子的境界。除了溃散态无法使用神击,其余状态下,当摄计魔士对女弟子使用神击时,女弟子头顶的真气会凝华成一枚仙丹,氣虚態和氣持態生成的仙丹种类不同。(初始状态是溃散态)

氣虚態 氣持態 潰散態
输气 气虚态获得饱满真气,进入气持态 已是气持状态,再给真气就要炸了 溃散态获得饱满真气,进入气虚态
卸气 气虚态卸去真气精华,进入溃散态 气持态卸去真气精华,进入气虚态 已是溃散状态,再卸真气就要挂了
神击 气虚态进行通天神击,获得还魂丹 气持态进行通天神击,获得转世丹 溃散状态还要神击,还让不让活了

摄计魔士三下五除二,就写了一版饱含if...else的女弟子类

女弟子.class

public class 女弟子 {
    final static int 溃散态 = 0;
    final static int 氣虚態 = 1;
    final static int 氣持態 = 2;

    int state = 溃散态;


    public void 输气() {
        if (state == 溃散态) {
            System.out.println("溃散态获得饱满真气,进入气虚态");
            state = 氣虚態;
        } else if (state == 氣虚態) {
            System.out.println("气虚态获得饱满真气,进入气持态");
            state = 氣持態;
        } else if (state == 氣持態) {
            System.out.println("已是气持状态,再给真气就要炸了");
        }
    }

    public void 卸气() {
        if (state == 溃散态) {
            System.out.println("已是溃散状态,再卸真气就要挂了");
        } else if (state == 氣虚態) {
            System.out.println("气虚态卸去真气精华,进入溃散态");
            state = 溃散态;
        } else if (state == 氣持態) {
            System.out.println("气持态卸去真气精华,进入气虚态");
            state = 氣虚態;
        }
    }

    public void 神击() {
        if (state == 溃散态) {
            System.out.println("溃散状态还要神击,还让不让活了");
        } else if (state == 氣虚態) {
            System.out.println("气虚态进行通天神击,获得还魂丹");
        } else if (state == 氣持態) {
            System.out.println("气持态进行通天神击,获得转世丹");
        }
    }


}

女弟子TestDrive.class

public class 女弟子TestDrive {
    public static void main(String[] args) {
        女弟子 女弟子 = new 女弟子();
        女弟子.卸气();
        女弟子.神击();
        女弟子.输气();
        女弟子.输气();
        女弟子.神击();
        女弟子.卸气();
        女弟子.神击();
    }
}

运行结果:

已是溃散状态,再卸真气就要挂了
溃散状态还要神击,还让不让活了
溃散态获得饱满真气,进入气虚态
气虚态获得饱满真气,进入气持态
气持态进行通天神击,获得转世丹
气持态卸去真气精华,进入气虚态
气虚态进行通天神击,获得还魂丹

摄计魔士看着代码,感觉总是有点心虚,但是一下子说不出为什么。不过,没过多久,他担心的事终于还是发生了。有一次在和夜芙蓉修炼时,夜芙蓉已经达到了气持态,原本摄计魔士应该使用卸气之术,但是由于误操作,使用了输气之术。按照惯例,夜芙蓉会反馈说“已是气持状态,再给真气就要炸了”,谁料因为长期修炼,夜芙蓉自身的能力大大提升,此时她进入到一个更高的状态——风巅态。摄计魔士尝试着对夜芙蓉用了一下神击,没想到竟然在夜芙蓉的头顶凝华出了一枚在江湖上消迹多年的“马丹”。这下好,还得把原来的代码改了。

氣虚態 氣持態 潰散態 風巅態
输气 气持态获得饱满真气,进入風巔態
卸气 风巅态卸去真气精华,进入气持态
神击 风巅态进行了通天神击,获得马丹

摄计魔士陷入了沉思,夜芙蓉体内真气与日俱增,这次是风巅态,谁知道下次会不会又达到一种新的境界,她每次达成新境界,都要在输气、卸气、神击三个方法里新搞出一个else分支,想着就让人抓狂。长痛不如短痛,摄计魔士决定把代码彻底改了去。

State.class

public interface State {
    public void 输气();

    public void 卸气();

    public void 神击();
}

氣持State .class

public class 氣持State implements State {
    女弟子V2 fuRong;

    public 氣持State(女弟子V2 fuRong) {
        this.fuRong = fuRong;
    }

    @Override
    public void 输气() {
        System.out.println("已是气持状态,再给真气就要炸了");
    }

    @Override
    public void 卸气() {
        System.out.println("气持态卸去真气精华,进入气虚态");
        fuRong.setState(fuRong.get氣虚State());
    }

    @Override
    public void 神击() {
        System.out.println("气持态进行通天神击,获得转世丹");
    }
}

氣虚State .class

public class 氣虚State implements State {
    女弟子V2 fuRong;

    public 氣虚State(女弟子V2 fuRong) {
        this.fuRong = fuRong;
    }

    @Override
    public void 输气() {
        System.out.println("气虚态获得饱满真气,进入气持态");
        fuRong.setState(fuRong.get氣持State());
    }

    @Override
    public void 卸气() {
        System.out.println("气虚态卸去真气精华,进入溃散态");
        fuRong.setState(fuRong.get溃散State());
    }

    @Override
    public void 神击() {
        System.out.println("气虚态进行通天神击,获得还魂丹");
    }
}

溃散State.class

public class 溃散State implements State {
    女弟子V2 fuRong;

    public 溃散State(女弟子V2 fuRong) {
        this.fuRong = fuRong;
    }

    @Override
    public void 输气() {
        System.out.println("溃散态获得饱满真气,进入气虚态");
        fuRong.setState(fuRong.get氣虚State());
    }

    @Override
    public void 卸气() {
        System.out.println("已是溃散状态,再卸真气就要挂了");
    }

    @Override
    public void 神击() {
        System.out.println("溃散状态还要神击,还让不让活了");
    }
}

女弟子V2.class

public class 女弟子V2 {
    State 氣持State;
    State 氣虚State;
    State 溃散State;

    State state = 溃散State;

    public 女弟子V2() {
        氣持State = new 氣持State(this);
        氣虚State = new 氣虚State(this);
        溃散State = new 溃散State(this);
        state = 溃散State; // 如果不在此处赋值的话,state肯定会为null
    }

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

    public State get氣持State() {
        return 氣持State;
    }

    public State get氣虚State() {
        return 氣虚State;
    }

    public State get溃散State() {
        return 溃散State;
    }


    public void 输气() {
        state.输气();
    }

    public void 卸气() {
        state.卸气();
    }

    public void 神击() {
        state.神击();
    }
}

女弟子TestDrive.class

public class 女弟子TestDrive {
    public static void main(String[] args) {
        女弟子V2 女弟子 = new 女弟子V2();
        女弟子.卸气();
        女弟子.神击();
        女弟子.输气();
        女弟子.输气();
        女弟子.神击();
        女弟子.卸气();
        女弟子.神击();
    }
}

运行结果

已是溃散状态,再卸真气就要挂了
溃散状态还要神击,还让不让活了
溃散态获得饱满真气,进入气虚态
气虚态获得饱满真气,进入气持态
气持态进行通天神击,获得转世丹
气持态卸去真气精华,进入气虚态
气虚态进行通天神击,获得还魂丹

可以看到测试类中,基本上一行没改,只是把女弟子换成了女弟子V2,运行结果也和之前的第一版完全相同,但是整个代码的结构完全不同,运用了State设计模式,使得在不同状态下,对应的行为放到了子类中,由此让每一种状态对修改关闭,而让女弟子本身对扩展开放,再有新的状态,就再加上一种状态的子类,避免了在女弟子这个类中大量if...else语句的使用。再加一个風巅態,应当是易如反掌的事了吧。

State模式:摄计魔士和夜芙蓉在暗房双修_第1张图片
State模式示意图

你可能感兴趣的:(State模式:摄计魔士和夜芙蓉在暗房双修)