状态模式(行为型)
来源:互联网 发布:wow台服数据库 编辑:程序博客网 时间:2024/06/16 08:25
在很多种情况下,一个对象的行为取决于一个或多个动态变化的属性,这些属性称为状态。例如水,液态时可以流动,气态时可以扩散,结冰时成了固态,这时既不能流动也不能扩散。例如使用键盘输入字符,当Caps Lock开启时,处于大写状态,这时输入的是大写字母,当Caps Lock关闭时,输入的是小写字母。例如用手机打电话,有信号并且话费充足时,才可以打电话,当没信号或者是处于欠费状态,就无法打电话了。
上面的例子都很接近于生活,浅显易懂。如果要对上面的这些逻辑进行编码实现,其实用if…else就可以,但当涉及的状态和行为很多时,这一大坨的代码就会变得很繁杂,维护起来很费力,也不利于扩展,当有新的状态时,就要对原来的代码进行比较大的改动,这时我们就需要考虑使用状态模式来让我们的代码变得更优雅,便于维护,便于扩展。
定义:允许一个对象在其内部状态改变时改变他的行为。
结构:
- Context:环境角色,定义客户端需要的接口,并且负责具体状态的切换
- State:抽象状态角色,为接口或者抽象类,负责对状态定义,并且封装环境角色以实现状态切换。
- ConcreteState:具体的状态角色,有两个职责:本状态的行为(本状态下要做的事情,以及本状态如何过渡到其他状态)管理和趋向状态处理;
适用场景:
- 行为随状态改变而改变,行为受状态约束的情况下
- 条件、分支判断语句的替代者:在程序中大量使用switch或者if判断语句导致程序结构不清晰,逻辑混乱,使用状态模式可以很好地避免这一问题,通过扩展子类实现条件的判断处理
UML:
下面就是状态模式的代码实现,这里以手机在有无话费状态下打电话为例子:
Context:本例中即为Class Phone
public class Phone { private State hasPhoneCharge; private State phoneArrears; private State nowState; //初始状态,该手机还剩下1块钱话费 private int phoneBill=1; public State getHasPhoneCharge() { return hasPhoneCharge; } public Phone setHasPhoneCharge(State hasPhoneCharge) { this.hasPhoneCharge = hasPhoneCharge; return this; } public State getPhoneArrears() { return phoneArrears; } public Phone setPhoneArrears(State phoneArrears) { this.phoneArrears = phoneArrears; return this; } public State getNowState() { return nowState; } public Phone setNowState(State nowState) { this.nowState = nowState; return this; } public int getPhoneBill() { return phoneBill; } public Phone setPhoneBill(int phoneBill) { this.phoneBill = phoneBill; return this; } public void call(){ nowState.call(); } public void payPhoneBill(int bill){ nowState.payPhoneBill(bill); }}
State:
public interface State { void call(); void payPhoneBill(int bill);}
ConcreteState:
public class PhoneArrears implements State{ Phone phone; public PhoneArrears(Phone phone){ this.phone = phone; } @Override public void call() { System.out.println("您的手机已停机,无法拨打电话"); } @Override public void payPhoneBill(int bill) { phone.setPhoneBill(phone.getPhoneBill()+bill); System.out.println("成功充值"+bill+"元,目前话费余额"+phone.getPhoneBill()); if(phone.getPhoneBill()>0){ phone.setNowState(phone.getHasPhoneCharge()); } }}public class HasPhoneCharge implements State{ Phone phone; public HasPhoneCharge(Phone phone){ this.phone = phone; } @Override public void call() { System.out.println("通话成功,扣除一元话费"); phone.setPhoneBill(phone.getPhoneBill()-1); if(phone.getPhoneBill()<=0){ System.out.println("您的手机因话费不足已停机,请充值"); phone.setNowState(phone.getPhoneArrears()); } } @Override public void payPhoneBill(int bill) { phone.setPhoneBill(phone.getPhoneBill()+bill); System.out.println("成功充值"+bill+"元,目前话费余额"+phone.getPhoneBill()); }}
Test:运行一下看下打印出的是什么!
public class Test { public static void main(String[] args) { Phone phone = new Phone(); //这里不是错误,想偷懒就弄成链式调用了 phone.setHasPhoneCharge(new HasPhoneCharge(phone)) .setPhoneArrears(new PhoneArrears(phone)) .setNowState(phone.getHasPhoneCharge()); phone.call(); phone.call(); phone.payPhoneBill(10); phone.call(); }}
总结:通过上面的代码我们可以看到,使用状态模式有效的避免被了过多的switch和if判断语句,降低了程序的复杂性,并且提高了可维护性。这样做程序的封装性也显得非常好,状态变换放置到类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的变换。状态模式有一个缺点就是子类太多(这也是大多数设计模式的共同缺点),如果一个事物有很多个状态使用状态模式就会有很多子类,尽管如此,也好过于去看一大坨的if…else语句,至少在逻辑上可以一目了然。
参考:https://github.com/nivance/DPModel/tree/master/src/dp/com/company/state
https://segmentfault.com/a/1190000003818435
http://dreamrunner.org/blog/2014/05/04/%E6%B5%85%E8%B0%88%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F13/
- 状态模式(行为型)
- 行为型模式-----状态模式(State)
- 行为型模式-状态
- 状态模式(行为型)
- 状态模式(行为型)
- 行为型模式--状态模式
- 行为型模式-状态模式
- 行为型模式--状态模式
- 状态模式State(对象行为型)
- 状态模式State(对象行为型)
- Java设计模式之行为型模式(状态模式)
- 行为型之状态模式
- 行为型之状态模式
- 行为模式:State(状态)
- 设计模式 - 行为型模式 - 状态模式
- 设计模式->行为型模式->状态模式
- 设计模式(十九)状态模式(State)-行为型
- 【设计模式】—-(20)状态模式(行为型)
- 关系型数据库与非关系型数据库的区别
- GLSurfaceView - 最简单的jni OpenGL ES渲染
- 机器学习算法总结
- Composer 常用命令
- 使用Markdown:你的博客可以更漂亮
- 状态模式(行为型)
- Ajax使用WCF实现小票pos机打印源码
- 公共组件使用手册
- spring中@param和mybatis中@param使用区别
- 软件开发学习网站
- 2016一路有你,2017一起同行
- Eclipse 插件安装、升级和卸载的方法
- Leetcode338. Counting Bits
- Android蓝牙基础方法