研磨设计模式 之 状态模式(State)1——跟着cc学设计系列
来源:互联网 发布:excel如何查重复数据 编辑:程序博客网 时间:2024/05/16 15:13
18.1 场景问题
18.1.1 实现在线投票
考虑一个在线投票的应用,要实现控制同一个用户只能投一票,如果一个用户反复投票,而且投票次数超过5次,则判定为恶意刷票,要取消该用户投票的资格,当然同时也要取消他所投的票。如果一个用户的投票次数超过8次,将进入黑名单,禁止再登录和使用系统。
该怎么实现这样的功能呢?
18.1.2 不用模式的解决方案
分析上面的功能,为了控制用户投票,需要记录用户所投票的记录,同时还要记录用户投票的次数,为了简单,直接使用两个Map来记录。
在投票的过程中,又有四种情况:
- 一是用户是正常投票
- 二是用户正常投票过后,有意或者无意的重复投票
- 三是用户恶意投票
- 四是黑名单用户
这几种情况下对应的处理是不一样的。看看代码吧,示例代码如下:
/**
* 投票管理
*/
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("进入黑名单,将禁止登录和使用本系统");
}
}
}
写个客户端来测试看看,是否能满足功能要求,示例代码如下:
public class Client {
public static void main(String[] args) {
VoteManager vm = new VoteManager();
for(int i=0;i<8;i++){
vm.vote("u1", "A");
}
}
}
运行结果如下:
恭喜你投票成功
请不要重复投票
请不要重复投票
请不要重复投票
你有恶意刷票行为,取消投票资格
你有恶意刷票行为,取消投票资格
你有恶意刷票行为,取消投票资格
进入黑名单,将禁止登录和使用本系统
18.1.3 有何问题
看起来很简单,是不是?幸亏这里只是示意,否则,你想想,在vote()方法中那么多判断,还有每个判断对应的功能处理都放在一起,是不是有点太杂乱了,那简直就是个大杂烩,如果把每个功能都完整的实现出来,那vote()方法会很长的。
一个问题是:如果现在要修改某种投票情况所对应的具体功能处理,那就需要在那个大杂烩里面,找到相应的代码块,然后进行改动。
另外一个问题是:如果要添加新的功能,比如投票超过8次但不足10次的,给个机会,只是禁止登录和使用系统3天,如果再犯,才永久封掉账号,该怎么办呢?那就需要改动投票管理的源代码,在上面的if-else结构中再添加一个else if块进行处理。
不管哪一种情况,都是在一大堆的控制代码里面找出需要的部分,然后进行修改,这从来都不是好方法,那么该如何实现才能做到:既能够很容易的给vote()方法添加新的功能,又能够很方便的修改已有的功能处理呢?
---------------------------------------------------------------------------
私塾在线学习网原创内容 跟着cc学设计系列 之 研磨设计模式
研磨设计讨论群【252780326】
原创内容,转载请注明出处【http://sishuok.com/forum/blogPost/list/5619.html】
---------------------------------------------------------------------------
- 研磨设计模式 之 状态模式(State)1——跟着cc学设计系列
- 研磨设计模式 之 装饰模式(Decorator)1——跟着cc学设计系列
- 研磨设计模式 之 备忘录模式(Memento)1——跟着cc学设计系列
- 研磨设计模式 之 代理模式(Proxy)1——跟着cc学设计系列
- 研磨设计模式之工厂方法模式-1——跟着cc学设计系列
- 研磨设计模式 之 访问者模式(Visitor)3——跟着cc学设计系列
- 研磨设计模式之工厂方法模式-2——跟着cc学设计系列
- 研磨设计模式之工厂方法模式-3——跟着cc学设计系列
- 研磨设计模式之工厂方法模式-4 ——跟着cc学设计系列
- 研磨设计模式之工厂方法模式-5——跟着cc学设计系列
- 研磨设计模式 之 解释器模式(Interpreter)2——跟着cc学设计系列
- 职责链模式——研磨设计模式——跟着cc学设计系列
- 命令模式——跟着cc学设计系列
- 桥接模式——跟着cc学设计系列
- 研磨设计模式 之 状态模式(State)
- 跟着CC学设计模式系列
- 跟着cc学设计模式
- 外观模式(Facade)——跟着cc学设计系列
- Linux下sort命令小结
- MySQL索引类型一览 让MySQL高效运行起来
- C语言宏定义##连接符和#符的使用
- 第38届ACM/ICPC亚洲区域赛杂记(BY TY)
- Unity Shaders简介
- 研磨设计模式 之 状态模式(State)1——跟着cc学设计系列
- 小霸王给微软、索尼、任天堂上的一堂课
- 动态规划(数形)
- scp命令
- VC++例说Windows窗口、视口以及GDI映射模式
- 关于new等函数对任务管理器中内存、句柄数变化的影响
- Java栈的实现(顺序栈、链式栈)及栈的应用
- GCC 选项和参数
- oracle 实时查询最耗CPU资源的SQL语句