1.场景模拟

考虑一个在线投票的应用,分为四种情况
正常投票

正常投票以后还继续重复投票

用户恶意投票

黑名单用户

2.不用模式的解决方案

package demo17.state.example1;
import java.util.*;
/**
* 投票管理
*/
public class VoteManager {
/**
* 记录用户投票的结果,Map<String,String>对应Map<用户名称,投票的选项>
*/
private Map<String,String> mapVote = new HashMap<String,String>();
/**
* 记录用户投票次数,Map<String,Integer>对应Map<用户名称,投票的次数>
*/
private Map<String,Integer> mapVoteCount = new HashMap<String,Integer>();
/**
* 投票
* @param user 投票人,为了简单,就是用户名称
* @param voteItem 投票的选项
*/
public void vote(String user,String voteItem){
//1:先为该用户增加投票的次数
//先从记录中取出已有的投票次数
Integer oldVoteCount = mapVoteCount.get(user);
if(oldVoteCount==null){
oldVoteCount = 0;
}
oldVoteCount = oldVoteCount + 1;
mapVoteCount.put(user, oldVoteCount); //2:判断该用户投票的类型,到底是正常投票、重复投票、恶意投票还是上黑名单
//然后根据投票类型来进行相应的操作
if(oldVoteCount==1){
//正常投票
//记录到投票记录中
mapVote.put(user, voteItem);
System.out.println("恭喜你投票成功");
}else if(oldVoteCount>1 && oldVoteCount<5){
//重复投票
//暂时不做处理
System.out.println("请不要重复投票");
}else if(oldVoteCount >= 5 && oldVoteCount<8){
//恶意投票
//取消用户的投票资格,并取消投票记录
String s = mapVote.get(user);
if(s!=null){
mapVote.remove(user);
}
System.out.println("你有恶意刷票行为,取消投票资格");
}else if(oldVoteCount>=8){
//黑名单
//记入黑名单中,禁止登录系统了
System.out.println("进入黑名单,将禁止登录和使用本系统");
}
}
}
************************************************************************************************
package demo17.state.example1; public class Client {
public static void main(String[] args) {
VoteManager vm = new VoteManager();
for (int i = 0; i < 8; i++) {
vm.vote("u1", "A");
}
}
}

3.问题所在(问题分析)

上述代码看起来很简单,实际上有很大的不妥之处,比如要添加新的功能,那怎么办呢?要在对应的一大堆的控制代码中找出需要的部分,然后进行修改,是很麻烦的。那么怎么很容易的扩展vote()这个方法呢?
由于刚刚学过了策略模式,很容易就想到要用策略模式来实现,因为感觉这里用策略模式正好。实际上则不然,这里不用策略模式实现,是因为策略模式重心在于分离算法,然后选择实现,大家可以发现,这个案例,没有什么需要计算的算法,都是一些相同的行为的次数的递增罢了,策略模式是不同行为的实现,针对不同的对象使用不同的策略,这里很明显不是,这里是相同的行为的次数的不同,导致结果不同,抽象化以后就是:对象的状态不同,导致结果不同,大家要仔细区分清楚。当然,你看这两个模式的客户端实现就能看出不同来。

那么,不用策略模式,用什么模式呢?

4.使用状态模式解决问题

4.1状态模式定义

允许一个对象在其内部状态改变时候,改变它的行为,对象看起来似乎修改了他的类。

4.2状态模式的结构和说明

结构图跟策略模式基本上是一样的,如下

4.3状态模式示例代码

package demo17.state.example2;

/**
* 封装与Context的一个特定状态相关的行为
*/
public interface State {
/**
* 状态对应的处理
*
* @param sampleParameter
* 示例参数,说明可以传入参数,具体传入 什么样的参数,传入几个参数,由具体应用来具体分析
*/
public void handle(String sampleParameter);
}
**********************************************************************
package demo17.state.example2; /**
* 实现一个与Context的一个特定状态相关的行为
*/
public class ConcreteStateA implements State {
public void handle(String sampleParameter) {
// 实现具体的处理
}
}
**********************************************************************
package demo17.state.example2; /**
* 实现一个与Context的一个特定状态相关的行为
*/
public class ConcreteStateB implements State {
public void handle(String sampleParameter) {
// 实现具体的处理
}
}
**********************************************************************
package demo17.state.example2; /**
* 定义客户感兴趣的接口,通常会维护一个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);
}
}

5.使用状态模式重写实例代码

5.1投票接口

package demo17.state.example3;
/**
* 封装一个投票状态相关的行为
*/
public interface VoteState {
/**
* 处理状态对应的行为
* @param user 投票人
* @param voteItem 投票项
* @param voteManager 投票上下文,用来在实现状态对应的功能处理的时候,
* 可以回调上下文的数据
*/
public void vote(String user,String voteItem,VoteManager voteManager);
}

5.2四个实现

package demo17.state.example3;

public class NormalVoteState implements VoteState{
public void vote(String user, String voteItem, VoteManager voteManager) {
//正常投票
//记录到投票记录中
voteManager.getMapVote().put(user, voteItem);
System.out.println("恭喜你投票成功");
}
} package demo17.state.example3; public class RepeatVoteState implements VoteState{
public void vote(String user, String voteItem, VoteManager voteManager) {
//重复投票
//暂时不做处理
System.out.println("请不要重复投票");
}
} package demo17.state.example3; 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("你有恶意刷票行为,取消投票资格");
}
} package demo17.state.example3; public class BlackWarnVoteState implements VoteState{
public void vote(String user, String voteItem, VoteManager voteManager) {
//待进黑名单警告状态
System.out.println("禁止登录和使用系统3天");
}
}

5.3投票管理

package demo17.state.example3;
import java.util.*;
/**
* 投票管理
*/
public class VoteManager {
/**
* 持有状态处理对象
*/
private VoteState state = null;
/**
* 记录用户投票的结果,Map<String,String>对应Map<用户名称,投票的选项>
*/
private Map<String,String> mapVote = new HashMap<String,String>();
/**
* 记录用户投票次数,Map<String,Integer>对应Map<用户名称,投票的次数>
*/
private Map<String,Integer> mapVoteCount = new HashMap<String,Integer>(); /**
* 获取记录用户投票结果的Map
* @return 记录用户投票结果的Map
*/
public Map<String, String> getMapVote() {
return mapVote;
} /**
* 投票
* @param user 投票人,为了简单,就是用户名称
* @param voteItem 投票的选项
*/
public void vote(String user,String voteItem){
//1:先为该用户增加投票的次数
//先从记录中取出已有的投票次数
Integer oldVoteCount = mapVoteCount.get(user);
if(oldVoteCount==null){
oldVoteCount = 0;
}
oldVoteCount = oldVoteCount + 1;
mapVoteCount.put(user, oldVoteCount); //2:判断该用户投票的类型,就相当于是判断对应的状态
//到底是正常投票、重复投票、恶意投票还是上黑名单的状态
if(oldVoteCount==1){
state = new NormalVoteState();
}else if(oldVoteCount>1 && oldVoteCount<5){
state = new RepeatVoteState();
}else if(oldVoteCount >= 5 && oldVoteCount<8){
state = new SpiteVoteState();
}else if(oldVoteCount>=8){
state = new BlackVoteState();
}
//然后转调状态对象来进行相应的操作
state.vote(user, voteItem, this);
}
}

5.4客户端不变

package demo17.state.example3;

public class Client {
public static void main(String[] args) {
VoteManager vm = new VoteManager();
for(int i=0;i<8;i++){
vm.vote("u1", "A");
}
}
}

6.状态模式讲解

6.1状态模式要点

状态和行为:对象的状态就是指对象实例的属性的值;而行为指的是对象的功能。

状态模式的功能:分离状态的行为,通过维护状态的变化,来调用不同状态对应不同的功能。


行为的平行性:注意是平行性,而不是平等性。

6.2状态模式的调用顺序图

6.3状态模式优缺点

优点:

简化应用逻辑控制

更好的分离状态和行为

更好的扩展性

显示化进行状态转换


缺点:

一个状态引入一个对应的状态处理类,会使得程序引入太多的状态类,使程序变得杂乱。

6.4状态模式本质

根据状态来分离和选择行为

设计模式19---设计模式之状态模式(State)(行为型)的更多相关文章

  1. Headfirst设计模式的C++实现——状态模式(State)

    state.h #ifndef _STATE_H_ #define _STATE_H_ class GumballMachine; class State { public: ; ; ; ; Stat ...

  2. 状态模式(State)-设计模式

    软件模式是将模式的一般概念应用于软件开发领域,即软件开发的 总体指导思路或参照样板.软件模式并非仅限于设计模式,还包括 架构模式.分析模式和过程模式等,实际上,在软件生存期的每一个阶段都存在着一些被认 ...

  3. 【转】设计模式 ( 十七) 状态模式State(对象行为型)

    设计模式 ( 十七) 状态模式State(对象行为型) 1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ...

  4. 设计模式 ( 十七) 状态模式State(对象行为型)

    设计模式 ( 十七) 状态模式State(对象行为型) 1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ...

  5. 乐在其中设计模式(C#) - 状态模式(State Pattern)

    原文:乐在其中设计模式(C#) - 状态模式(State Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 状态模式(State Pattern) 作者:webabcd 介绍 允 ...

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

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

  7. 北风设计模式课程---状态模式State(对象行为型)

    北风设计模式课程---状态模式State(对象行为型) 一.总结 一句话总结: 状态模式 具体状态的行为在具体的状态类中就解决,不用交给外部做判断.实质是将多条件判断弄成了多个类,在不同的类中做判断 ...

  8. 二十四种设计模式:状态模式(State Pattern)

    状态模式(State Pattern) 介绍允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它所属的类. 示例有一个Message实体类,对它的操作有Insert()和Get()方法, ...

  9. 设计模式 笔记 状态模式 State

    //---------------------------15/04/28---------------------------- //State  状态模式----对象行为型模式 /* 1:意图: ...

  10. 设计模式(java)--状态模式

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

随机推荐

  1. cancel-ng-swipe-right-on-child

    <!DOCTYPE html> <html lang="en" ng-app="myapp"> <head> <met ...

  2. Web服务图片压缩,nginx+lua生成缩略图

    背景 目前而言,用移动端访问Web站点的用户越来越多,图片对流量的消耗是比较大的,之前一个用户用我们网站的app浏览的时候,2个小时耗去了2个G的流量,这是个很严重的问题,需要对图片进行压缩,减少对用 ...

  3. css命名为何不推荐使用下划线_

    一直习惯了在命名CSS样式名时使用下划线“_”做为单词的分隔符,这也是在写JS时惯用的写法. 用过CSS hack的朋友应该知道,用下划线命名也是一种hack,如使用“_style”这样的命名,可以让 ...

  4. undefined 和 null 的异同

    在javascript中,undefined和Null是两个比较特殊的值.但有时候在判断时就有点迷糊.依个人浅见,整理如下: 1.数据类型 众多周知,在javascript中存在五种基本类型,即und ...

  5. phalcon安装和输出 hello word

    1:下载和安装Wampserver2.4-x86.exe 服务器: 2:到phalcon官方网站下载对应的dll文件 phalcon_x86_VC9_php5.4.0_1.2.5 我下的是这个版本 所 ...

  6. Pyhon + Django 1.7.2 tutorial + virtualenv简单使用

    最近工作中要用到python,先前没怎么接触过,把python本身的语法以及特性撸过一边之后,这两天按着django官方的文档倒腾了几天, 文档非常详细,本人英语水平也就那样,大体没什么压力,建议像我 ...

  7. intel集成显卡linux驱动安装

    https://01.org/linuxgraphics/documentation/build-guide-0 https://01.org/linuxgraphics/community/mesa ...

  8. POJ 1637 混合图欧拉回路

    先来复习一下混合图欧拉回路:给定一张含有单向边和双向边的图,使得每一点的入度出度相同. 首先对于有向边来说,它能贡献的入度出度是确定的,我们不予考虑.对于无向图,它可以通过改变方向来改变两端点的出入度 ...

  9. 【动态规划】POJ 1161 & ZOJ1463 & XMU 1033 Brackets sequence

    题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1033 http://poj.org/problem?id=1141 ZOJ目前挂了. ...

  10. combobox的不常用的方法和将txt文本内容加到textbox中显示

    将一个的datatable绑定到下拉框,指定显示某列的数据 cbx.DataSource = null; DataSet dsJH = new DataSet(); OperatePort.Opera ...