简明 状态模式(5.8)

当一个类A的某个成员变量的值变化时,可能导致多个行为表现得不同。将该成员变量封装成类型的模式,即为状态模式(state pattern)。

编程技巧:以多态来重构分支结构。

设计思路:解决状态加入、状态转换、状态对行为的影响问题。



状态决定行为

不考虑状态转换,非常easy看到状态决定行为的场景。“朋友来了有好酒,若是那豺狼来了,迎接它的有猎枪”。

不在状态。该赢的比赛都会输。

例程 4-3 又见分支结构
package property.state;
public class Man{
    private boolean isHappy;//典型的flag,两种状态
    public String sayHello() {
        String greeting="";
        if(isHappy){
            greeting ="你好,我的朋友";
        }else{
            greeting ="好";
        }
        return greeting;
    }
    public String sayGoodbye() {
        return isHappy? "再抱抱!

":"再见,再也不见"; } public static void main(String[] args) { Man one = new Man(); one.isHappy =true;//false System.out.println(one.sayHello()); System.out.println(one.sayGoodbye()); } }

这样的Man没有城府,当成员变量isHappy取值不同一时候,Man的sayHello()和sayGoodbye()等多个行为表现得不同。

在简单场景中,if-else更简洁。然而。关键成员变量能够是int或枚举类型表示的好感度。或某个类型如顾客(土豪、凡人、钓丝)。

  • 随着状态取值可能性的加入,分支块越来越大。sayHello()和sayGoodbye()代码都变得庞大。

  • 特别是添加新的状态值,在分支结构下违反OCP

从编程技巧上看,状态模式和策略模式、工厂方法模式一样。以多态来重构分支结构

重构的要点:①以状态类State替代boolean、int、枚举类型或类型(注意这样的情况)的分支推断參数。显然有多少分支。State将相应有多少子类。②状态类State将全部具有上述分支推断的方法,提取为自己的接口,State的子类分别给出配套的实现

例程 4-4 State的子类们
package property.state;
public interface State{
    public String sayHello();
    public String sayGoodbye();
}
package property.state;
public class FriendState implements State{
    @Override public String sayHello(){
        return "你好,我的朋友";
    }
    @Override public String sayGoodbye(){
        return "再抱抱!";
    }
}//OpposingState略
package property.state;
public class Man2{
    private State state;
    public String sayHello() {
        return state.sayHello();       
    }
    public String sayGoodbye() {
        return state.sayGoodbye();        
    }
    
    public static void main(String[] args) {
		Man2 one = new Man2();
		one.state  =new FriendState();//isHappy = true
		System.out.println(one.sayHello());
		System.out.println(one.sayGoodbye());
	}
}

在不考虑状态转换时,单纯从代码上看,状态模式的State封装多个方法,而策略模式仅封装一个方法。此时,

状态模式与策略模式的关系,如同抽象工厂与工厂方法的关系。

尽管状态模式封装多个方法,与抽象工厂一样,不会出现[3.2.4方法类型化]的例程3-5那样的组合爆炸,由于多个方法在一个状态下是配套的,而非随意的组合。


yqj2065在设计模式学习难度系数排名中。状态模式给的难度系数高达5分(10分制)。

假设不过策略模式基础上的一变多,难度系数应该是1.难过


在Man的代码中是通过设置isHappy的值改变其状态。在Man2中是通过设置State的对象类型改变其状态。状态之间的变换由外界控制,或者说,多种状态是切割的、无关的。这样的情况下,学习状态模式的难度系数最多是1。

可是,状态模式最有趣的地方正是其状态的变迁。

将涉及一个比較高端的术语Finite State Machine 有限状态机



2.状态的变迁

.....


posted @ 2017-08-10 17:27  gccbuaa  阅读(139)  评论(0编辑  收藏  举报