Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

目录

状态模式

状态模式看起来和策略模式很像,但是是两个不一样的设计模式。状态模式是一个类根据内部的状态动态的选择行为。策略模式一般用于算法,通过设置不同的策略类来执行不同的算法。

简介

状态模式允许一个对象在其内部状态改变的时候改变其行为,这个对象看上去就像是改变了它的类一样。

状态模式把所研究的对象的【行为】包装在不同的【状态对象】里,每一个状态对象都属于抽象状态类的一个子类。

状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。

角色

  • 抽象状态类State:定义一个或一组接口,表示该状态下类的行为
  • 具体状态类ConcreteState:实现抽象状态类中定义的接口,从而达到不同状态下的不同行为
  • 环境类Context:定义客户感兴趣的接口,维护一个抽象状态类的子类的实例,这个实例代表对象当前的状态

和策略模式的比较

状态模式和策略模式的结构几乎完全一样,但它们的目的却完全不一样。

状态模式的行为是平行的、不可替换的,策略模式的行为是彼此独立、可相互替换的。

状态模式和策略模式都是为了实现解耦,避免一大堆的if-else的写法,但是状态模式更多的是适合不同状态下,同样的行为有不同的响应。根据实际生活来说,这种模式适合有明显的状态区分的时候。比如电视的开,关就是两种状态。

状态模式的关键点在于不同的状态下对于同一行为有不同的响应,这其实就是一个将if-else用多态来实现的具体实例

状态模式将所有与一个特定状态相关的行为都放入一个状态对象中,它提供了一个更好的方法来组织与特定状态相关的代码,将繁琐的状态判断转换成结构清晰的状态类族,在避免代码膨胀的同时也保证了可扩展性和可维护性

使用场景

  • 一个类的状态决定了他的行为,而且在运行时必须根据当前的状态来改变行为。
  • 跟策略模式一样,解决一大堆分支语句的存在。

优缺点:

  • 优点:将所有的状态和该状态的行为封装在同一个实现类中,然后有一个共同的接口,代码结构清晰,便于扩展和修改。
  • 缺点:也是要增加很多类

案例一

下面我们以日常开发中的登录功能来简单应用下状态模式

在登录模块中一般我们会根据用户是否是登录状态而有不同的操作,这里简单模拟2个操作,转发和评论

public interface UserState {
void forward(Context context); //转发
void comment(Context context); //评论
}

登录状态,调用转发和评论直接简单地弹出个Toast

public class LoginedState implements UserState {

    @Override
public void forward(Context context) {
Toast.makeText(context, "转发成功", Toast.LENGTH_SHORT).show();
} @Override
public void comment(Context context) {
Toast.makeText(context, "评论成功", Toast.LENGTH_SHORT).show();
}
}

未登录状态,调用转发和评论跳转到登录页面,这里直接简单地弹出登录的提示

public class LogoutState implements UserState {

    @Override
public void forward(Context context) {
Toast.makeText(context, "未登录,跳转到登录页面", Toast.LENGTH_SHORT).show();
} @Override
public void comment(Context context) {
Toast.makeText(context, "未登录,跳转到登录页面", Toast.LENGTH_SHORT).show();
}
}

相当于将每一个条件分支下的行为全部放入了一个独立的类中,如果不采用这种模式,则针对每一种行为都必须采取if-else方式判断

状态模式把对象的行为包装在不同的状态对象里,状态模式的意图是让一个对象在其内部状态发生改变的时候,其行为也随之改变

状态模式的行为是平行的、不可替换的

下面我们看看对外提供服务的环境类

public class LoginContext {
private UserState userState = new LoginedState(); //用户状态,默认为登录状态 public void setUserState(UserState userState) { //设置用户状态
this.userState = userState;
} public void forward(Context context) {
userState.forward(context);
} public void comment(Context context) {
userState.comment(context);
}
}

下面我们看看怎么调用:

LoginContext context = LoginContext();
context.forward(MainActivity.this); //默认是登录状态,所以可以直接调用转发功能 context.setUserState(new LogoutState()); //登录状态改为未登录
context.forward(MainActivity.this); //注销登录后再调用转发或是评论功能,执行的就会是弹出登录提示

通过上面的例子我们可以看出,状态模式把对象的不同状态下的行为封装起来,对象的状态改变了,对象的行为也会改变。

案例二

抽象状态类

interface IState {
void open(); //电梯门开启动作
void close();//电梯关闭动作
void run();//运行电梯动作
void stop();//停止电梯动作
}

具体状态类

class OpenningState implements IState {
private Context context; public OpenningState(Context context) {
this.context = context;
} @Override
public void open() {
System.out.println("电梯门开启...");
} @Override
public void close() {
context.setState(Context.closeingState);//状态修改
context.getState().close(); //动作委托给CloseState来执行
} @Override
public void run() {
System.out.println("------------------电梯门开启状态下运行?要死啊,你!");
} @Override
public void stop() {
System.out.println("------------------电梯门开启状态下停止?额,这个本来就应该是这样的吧!");
}
}
class ClosingState implements IState {
private Context context; public ClosingState(Context context) {
this.context = context;
} @Override
public void close() {
System.out.println("电梯门关闭...");
} @Override
public void open() {
context.setState(Context.openningState);
context.getState().open();
} @Override
public void run() {
context.setState(Context.runningState);
context.getState().run();
} @Override
public void stop() {
context.setState(Context.stoppingState);
context.getState().stop();
}
}
class RunningState implements IState {
private Context context; public RunningState(Context context) {
this.context = context;
} @Override
public void close() {
System.out.println("------------------运行状态下关闭电梯门?电梯门本来就是关着的!");
} @Override
public void open() {
System.out.println("------------------运行状态下开电梯门?你疯了!");
} @Override
public void run() {
System.out.println("电梯上下跑...");
} @Override
public void stop() {
context.setState(Context.stoppingState);
context.getState().stop();
}
}
class StoppingState implements IState {
private Context context; public StoppingState(Context context) {
this.context = context;
} @Override
public void close() {
System.out.println("------------------停止状态下关门?电梯门本来就是关着的!");
} @Override
public void open() {
context.setState(Context.openningState);
context.getState().open();
} @Override
public void run() {
context.setState(Context.runningState);
context.getState().run();
} @Override
public void stop() {
System.out.println("电梯停止了...");
}
}

环境类

class Context {
public static OpenningState openningState;
public static ClosingState closeingState;
public static RunningState runningState;
public static StoppingState stoppingState; private IState state; public IState getState() {
return state;
} public Context() {
openningState = new OpenningState(this);
closeingState = new ClosingState(this);
runningState = new RunningState(this);
stoppingState = new StoppingState(this);
} public void setState(IState state) {
this.state = state;
} public void open() {
state.open();
} public void close() {
state.close();
} public void run() {
state.run();
} public void stop() {
state.stop();
}
}

测试

class Test {
public static void main(String[] args) {
Context context = new Context();
IState[] states = {new OpenningState(context), new ClosingState(context), new RunningState(context), new StoppingState(context)};
for (IState state : states) {
System.out.println("当前状态【" + state.getClass().getSimpleName() + "】");
context.open();
context.close();
context.run();
context.stop();
}
}
}

2016-10-20

State 状态模式 MD的更多相关文章

  1. C++设计模式-State状态模式

    State状态模式作用:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. UML图如下: State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为. ...

  2. State状态模式

    1.简介 在日常开发中,某些对象的状态如果发生改变,对应的行为也将发生改变,那么如何在运行时根据对象的状态动态的改变对象的行为,同时不产生紧耦合关系(即使用if else或者swith所带来的紧耦合关 ...

  3. 设计模式---状态变化模式之state状态模式(State)

    前提:状态变化模式 在组建构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”模式为这一个问题提供了一种解决方案. 典型模式 状态模式:Stat ...

  4. 设计模式21:State 状态模式(行为型模式)

    State 状态模式(行为型模式) 动机(Motivation) 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态的行为就可能完全不同. ...

  5. 19、State 状态模式

    “人有悲欢离合,月有阴晴圆缺”,包括人在内,很多事物都具有多种状态,而且在不同状态下会具有不同的行为,这些状态在特定条件下还将发生相互转换.就像水,它可以凝固成冰,也可以受热蒸发后变成水蒸汽,水可以流 ...

  6. 程序设计模式 —— State 状态模式

    我应该如何阅读? 本文将使用优雅的文字风格来告诉你什么是状态模式. 注意: 1.在阅读本文之前请保证你已经掌控了 面对对象的思想与 多态的基本概念,否则将难以理解. 2.本文实现将用C++实现,你不一 ...

  7. JAVA设计模式--State(状态模式)

    状态模式(State Pattern)是设计模式的一种,属于行为模式. 定义(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要 ...

  8. 设计模式之 State 状态模式

    状态模式的核心在于 1. 状态的转换导致行为(Handle)的差异,比如人的状态是饿的时候,吃(Handle)的行为是2个馒头,人状态是不太饿的时候,吃(Handle)的行为是半个馒头 2. Stat ...

  9. State 状态模式

    简介 状态模式允许一个对象在其内部[状态]改变的时候改变其[行为].这个对象看上去就像是改变了它的类一样. 用一句话来表述,状态模式把所研究的对象的[行为]包装在不同的[状态对象]里,[每一个状态对象 ...

随机推荐

  1. 打开tcp_tw_recycle引起的一次投诉分析

    背景: 我们有个基于oauth2.0协议给第三方授权以及信息的业务,年前对接入层.业务层做了次迁移.业务架构简单介绍下: lvs接入---> nginx ---> tomcat   问题: ...

  2. 一个UICollectionView自定义layout的实现

      #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @ ...

  3. 深入理解ajax系列第四篇

    前面的话 现代Web应用中频繁使用的一项功能就是表单数据的序列化,XMLHttpRequest 2级为此定义了FormData类型.FormData为序列化表单以及创建与表单格式相同的数据提供了便利. ...

  4. zip函数实际应用

    一个需求,把两个列表要同时用for循环贴到模板上,用zip在后端组成  元祖组成的列表  这样在模板就可以用.0   .1的方式,类似python中 x[0]   x[1] 显示出来. html显示: ...

  5. Spring Boot 基础配置

    之前简单接触了一些Spring Boot ,并且写了一个简单的 Demo .本文就来简单学习一下 Spring Boot 的基础配置. 一.Spring Boot 项目入口 上文中有写到,Spring ...

  6. android无后缀二进制执行文件替代apk实现程序功能

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha android无后缀二进制执行文件替代apk实现程序功能 实现将data/Android ...

  7. Where should we fork this repository?

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 我们应该在哪里分叉这个存储库? Where should we fork this re ...

  8. 【20181102T1】优美的序列【二分+ST表】

    题面 [正解] 相当于是 \(GCD_{i=L}^{R} A_i = min_{i=L}^{R} \{A_i\}\) 然后GCD可以用ST表实现\(O(log A_i)\)查询 并且GCD是递减的,所 ...

  9. BZOJ.3110.[ZJOI2013]K大数查询(整体二分 树状数组/线段树)

    题目链接 BZOJ 洛谷 整体二分求的是第K小(利用树状数组).求第K大可以转为求第\(n-K+1\)小,但是这样好像得求一个\(n\). 注意到所有数的绝对值\(\leq N\),将所有数的大小关系 ...

  10. 浅析SDWebImage

    浅析SDWebImage 在日常的开发过程中,如果去优雅的访问网络的图片并去管理每个工程必须要面对的问题,如果想要在工程里面提供易用.简洁.方便管理的解决方案还是很有挑战的,毕竟还要兼顾图片文件的缓存 ...