读书人

状态模式二

发布时间: 2013-12-15 22:17:18 作者: rapoo

状态模式2
?

(2)应用状态模式来解决的思路

?????? 仔细分析上面的问题,会发现,那几种用户投票的类型,就相当于是描述了人员的几种投票状态,而各个状态和对应的功能处理具有很强的对应性,有点类似于“一个萝卜一个坑”,各个状态下的处理基本上都是不一样的,也不存在可以相互替换的可能。

?????? 为了解决上面提出的问题,很自然的一个设计就是首先把状态和状态对应的行为从原来的大杂烩代码中分离出来,把每个状态所对应的功能处理封装在一个独立的类里面,这样选择不同处理的时候,其实就是在选择不同的状态处理类。

?????? 然后为了统一操作这些不同的状态类,定义一个状态接口来约束它们,这样外部就可以面向这个统一的状态接口编程,而无需关心具体的状态类实现了。

?????? 这样一来,要修改某种投票情况所对应的具体功能处理,那就是直接修改或者扩展某个状态处理类的功能就可以了。而要添加新的功能就更简单,直接添加新的状态处理类就可以了,当然在使用Context的时候,需要设置使用这个新的状态类的实例。

18.2.2? 模式结构和说明

状态模式的结构如图18.1所示:

?状态模式二

图18.1? 状态模式结构示意图

Context

?????? 环境,也称上下文,通常用来定义客户感兴趣的接口,同时维护一个来具体处理当前状态的实例对象。

State

?????? 状态接口,用来封装与上下文的一个特定状态所对应的行为。

ConcreteState

?????? 具体实现状态处理的类,每个类实现一个跟上下文相关的状态的具体处理。

18.2.3? 状态模式示例代码

(1)首先来看状态接口,示例代码如下:

/**

?* 封装与Context的一个特定状态相关的行为

?*/

public interface State {

??? /**

??? ?* 状态对应的处理

??? ?* @param sampleParameter 示例参数,说明可以传入参数,具体传入

??? ?*???????????? 什么样的参数,传入几个参数,由具体应用来具体分析

??? ?*/

??? public void handle(String sampleParameter);

}

(2)再来看看具体的状态实现,目前具体的实现ConcreteStateA和ConcreteStateB示范的是一样的,只是名称不同,示例代码如下:

/**

?* 实现一个与Context的一个特定状态相关的行为

?*/

public class ConcreteStateA implements State {

??? public void handle(String sampleParameter) {

?????? //实现具体的处理

??? }

}

/**

?* 实现一个与Context的一个特定状态相关的行为

?*/

public class ConcreteStateB implements State {

??? public void handle(String sampleParameter) {

?????? //实现具体的处理

??? }

}

(3)再来看看上下文的具体实现,上下文通常用来定义客户感兴趣的接口,同时维护一个具体的处理当前状态的实例对象。示例代码如下:

/**

?* 定义客户感兴趣的接口,通常会维护一个State类型的对象实例

?*/

public class Context {

??? /**

??? ?* 持有一个State类型的对象实例

??? ?*/

??? private State state;

??? /**

??? ?* 设置实现State的对象的实例

??? ?* @param state 实现State的对象的实例

??? ?*/

??? public void setState(State state) {

?????? this.state = state;

??? }

??? /**

??? ?* 用户感兴趣的接口方法

??? ?* @param sampleParameter 示意参数

??? ?*/

??? public void request(String sampleParameter) {

?????? //在处理中,会转调state来处理

?????? state.handle(sampleParameter);

??? }

}

18.2.4? 使用状态模式重写示例

?????? 看完了上面的状态模式的知识,有些朋友跃跃欲试,打算使用状态模式来重写前面的示例,要使用状态模式,首先就需要把投票过程的各种状态定义出来,然后把这些状态对应的处理从原来大杂烩的实现中分离出来,形成独立的状态处理对象。而原来的投票管理的对象就相当于Context了。

??????

图18.2? 状态模式的示例程序机构示意图

(1)先来看状态接口的代码实现,示例代码如下:

/**

?* 封装一个投票状态相关的行为

?*/

public interface VoteState {

??? /**

??? ?* 处理状态对应的行为

??? ?* @param user 投票人

??? ?* @param voteItem 投票项

??? ?* @param voteManager 投票上下文,用来在实现状态对应的功能处理的时候,

??? ?*??????????????????? 可以回调上下文的数据

??? ?*/

??? public void vote(String user,String voteItem

,VoteManager voteManager);

}

(2)定义了状态接口,那就该来看看如何实现各个状态对应的处理了,现在的实现很简单,就是把原来的实现从投票管理类里面分离出来就可以了。先看正常投票状态对应的处理,示例代码如下:

public class NormalVoteState implements VoteState{

??? public void vote(String user, String voteItem

,VoteManager voteManager) {

?????? //正常投票

?????? //记录到投票记录中

?????? voteManager.getMapVote().put(user, voteItem);

?????? System.out.println("恭喜你投票成功");

??? }

}

?????? 接下来看看重复投票状态对应的处理,示例代码如下:

public class RepeatVoteState implements VoteState{

??? public void vote(String user, String voteItem

,VoteManager voteManager) {

?????? //重复投票

?????? //暂时不做处理

?????? System.out.println("请不要重复投票");

??? }

}

接下来看看恶意投票状态对应的处理,示例代码如下:

public class SpiteVoteState implements VoteState{

??? public void vote(String user, String voteItem

,VoteManager voteManager) {

?????? //恶意投票

?????? //取消用户的投票资格,并取消投票记录

?????? String s = voteManager.getMapVote().get(user);

?????? if(s!=null){

?????????? voteManager.getMapVote().remove(user);

?????? }

?????? System.out.println("你有恶意刷票行为,取消投票资格");

??? }

}

接下来看看黑名单状态对应的处理,示例代码如下:

public class BlackVoteState implements VoteState{

??? public void vote(String user, String voteItem

,VoteManager voteManager) {

?????? //黑名单

?????? //记入黑名单中,禁止登录系统了

?????? System.out.println("进入黑名单,将禁止登录和使用本系统");

??? }

}

(3)定义好了状态接口和状态实现,看看现在的投票管理,相当于状态模式中的上下文,相对而言,它的改变如下:

读书人网 >编程

热点推荐