Design Pattern: State 模式

本文通过一个煤气灶开关的例子,介绍了状态模式的基本概念及其实现方法,包括如何利用对象自身控制状态转换,以及如何处理顺时针和逆时针两种方向的状态转换。

如果您不了解TCP的连线方式,在看 Gof 的书介绍State模式时,大概会看得一头雾水吧!TCP的连线状态图,光是要了解就要花点精神了,它的连线状态很多,用来说明状态模式确实很适合,但不适合教导初学模式的人。

由简单的开始会比较好理解状态模式的作用,先来看一个例子,如果您有一个只能顺时针转动的瓦斯开关,转动一次的状态为off、 small fire、medium fire与large fire,您如何在程式中控制状态的变化与行为呢?一个最简单的方式就是用if..else或是switch流程来控制,例如:

  • State.java
public class State { 
    private int state;

    public State() { 
        state = 0; 
    } 

    public void switchFire() { 
        if (state == 0) { 
            state = 1; 
            System.out.println( "small fire" ); 
        } else if (state == 1) { 
            state = 2; 
            System.out.println( "medium fire" ); 
        } else if (state == 2) { 
            state = 3; 
            System.out.println( "large fire" ); 
        } else { 
            state = 0; 
            System.out.println( "turning off" ); 
        } 
    } 
}  

 

  • Main.java
public class Main { 
     public static void main(String[] args) { 
        State state = new State();

        state.switchFire(); 
        state.switchFire(); 
        state.switchFire(); 
        state.switchFire(); 
    } 
} 


这个方法很简单,每个人都会,但如果您的状态变化并不是流水式的变化,而是像TCP连线状态一样,会是一个网络图的时候,用 if...else或switch来写的话,您的程式就会乱的不像话了;来考虑如何让物件控制自己的状态转换与所应表现的行为,这个程式可以这样改写:

  • IState.java
public interface IState { 
    public void switchFire(FireSwitch sw); 
} 

 

  • OffState
public class OffState implements IState { 
    public void switchFire(FireSwitch sw) { 
        sw.setState(new SmallState()); 
        System.out.println( "small fire" ); 
    } 
} 

 

  • SmallState.java
public class SmallState implements IState { 
    public void switchFire(FireSwitch sw) { 
        sw.setState(new MediumState()); 
        System.out.println( "medium fire" ); 
    } 
}  

 

  • MediumState.java
public class MediumState implements IState { 
    public void switchFire(FireSwitch sw) { 
        sw.setState(new LargeState()); 
        System.out.println( "large fire" ); 
    } 
}  

 

  • LargeState.java
public class LargeState implements IState { 
    public void switchFire(FireSwitch sw) { 
        sw.setState(new OffState()); 
        System.out.println( "off fire" ); 
    } 
}  

 

  • FireSwitch.java
public class FireSwitch { 
    private State current;

    public FireSwitch() { 
        current = new OffState(); 
    }

    public void setState(State s) { 
        current = s; 
    }

    public void switchFire() { 
        current.switchFire(this); 
    }
} 

 

  • Main.java
public class Main { 
    public static void main(String[] args) { 
        FireSwitch fireSwitch = new FireSwitch();
        fireSwitch.switchFire(); 
        fireSwitch.switchFire(); 
        fireSwitch.switchFire(); 
        fireSwitch.switchFire(); 
    } 
} 


程式执行结果与上一个例子是一样的,但这次并没有用流程控制来进行状态转换,而由物件自行控制自己的状态,与必须表现的行为,这个方式就是State 模式,将这个例子的 UML 类别结构画出就如下所示:

再进一步考虑开关可以顺时针与逆时针转动,这时如果您仍以if...else或switch来写,就会让流程显示复杂,来看看如何使用状态模式来撰写:
  • IState.java
public interface IState { 
    public void switchClockWise(FireSwitch sw); 
    public void switchCountClock(FireSwitch sw); 
}  

 

  • OffState.java
public class OffState implements IState { 
    public void switchClockWise(FireSwitch sw) { 
        sw.setState(new SmallState()); 
        System.out.println("small fire"); 
    }

    public void switchCountClock(FireSwitch sw) { 
        sw.setState(new LargeState()); 
        System.out.println("large fire"); 
    } 
}  

 

  • SmallState.java
public class SmallState implements IState { 
    public void switchClockWise(FireSwitch sw) { 
        sw.setState(new MediumState()); 
        System.out.println("medium fire"); 
    } 

    public void switchCountClock(FireSwitch sw) { 
        sw.setState(new OffState()); 
        System.out.println("off fire"); 
    } 
}  

 

  • MediumState.java
public class MediumState implements IState { 
    public void switchClockWise(FireSwitch sw) { 
        sw.setState(new LargeState()); 
        System.out.println("large fire"); 
    }
 
    public void switchCountClock(FireSwitch sw) { 
        sw.setState(new SmallState()); 
        System.out.println("small fire"); 
    } 
}  

 

  • LargeState.java
public class LargeState implements State { 
    public void switchClockWise(FireSwitch sw) { 
        sw.setState(new OffState()); 
        System.out.println("off fire"); 
    }

    public void switchCountClock(FireSwitch sw) { 
        sw.setState(new MediumState()); 
        System.out.println("medium fire"); 
    } 
}  

 

  • FireSwitch.java
public class FireSwitch { 
    private State current;

    public FireSwitch() { 
        current = new OffState(); 
    }

    public void setState(State s) { 
        current = s; 
    }

    public void switchClockWise() { 
        current.switchClockWise(this); 
    }

    public void switchCountClock() { 
       current.switchCountClock(this); 
    } 
}  

 

  • Main.java
public class Main { 
    public static void main(String[] args) { 
        FireSwitch fireSwitch = new FireSwitch();

        fireSwitch.switchClockWise(); 
        fireSwitch.switchClockWise(); 
        fireSwitch.switchClockWise(); 
        fireSwitch.switchClockWise(); 

        System.out.println();

        fireSwitch.switchCountClock(); 
        fireSwitch.switchCountClock(); 
        fireSwitch.switchCountClock(); 
        fireSwitch.switchCountClock(); 
    } 
} 


接下来您可以任意的转动开关了,无论是顺时针转动或是逆时针转动,状态的转换都由物件自己来表现,这是双向状态转换下的例子,如果一个状态可能转换至三个以上的状态,使用State模式就更可以看出它的好处了,就像Gof的TCP连线例子一样,如果您了解TCP连线,可以看看原书是如何实现TCP连线之间的状态转换的。

提供了基于BP(Back Propagation)神经网络结合PID(比例-积分-微分)控制策略的Simulink仿真模型。该模型旨在实现对杨艺所著论文《基于S函数的BP神经网络PID控制器及Simulink仿真》中的理论进行实践验证。在Matlab 2016b环境下开发,经过测试,确保能够正常运行,适合学习和研究神经网络在控制系统中的应用。 特点 集成BP神经网络:模型中集成了BP神经网络用于提升PID控制器的性能,使之能更好地适应复杂控制环境。 PID控制优化:利用神经网络的自学习能力,对传统的PID控制算法进行了智能调整,提高控制精度和稳定性。 S函数应用:展示了如何在Simulink中通过S函数嵌入MATLAB代码,实现BP神经网络的定制化逻辑。 兼容性说明:虽然开发于Matlab 2016b,但理论上兼容后续版本,可能会需要调整少量配置以适配不同版本的Matlab。 使用指南 环境要求:确保你的电脑上安装有Matlab 2016b或更高版本。 模型加载: 下载本仓库到本地。 在Matlab中打开.slx文件。 运行仿真: 调整模型参数前,请先熟悉各模块功能和输入输出设置。 运行整个模型,观察控制效果。 参数调整: 用户可以自由调节神经网络的层数、节点数以及PID控制器的参数,探索不同的控制性能。 学习和修改: 通过阅读模型中的注释和查阅相关文献,加深对BP神经网络与PID控制结合的理解。 如需修改S函数内的MATLAB代码,建议有一定的MATLAB编程基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值