1、实现在线投票
需求: 在线投票,要实现控制统一用户只能头投一票,如果一个用户反复投票,而且投票次数超过5次,则判定为恶意刷票,要取消该用户投票的资格,当然同时也要取消他所有的投票;如果一个用户的投票次数超过8次,将进入黑名单,禁止再登录和使用系统。
2、传统的解决方案
public class VoteManager2 {
/**
* 记录用户投票的结果,map<用户名称,投票的选项>
*/
private Map<String,String> mapVote = new HashMap<>();
/**
* 记录用户投票次数
*/
private Map<String,Integer> mapVoteCount = new HashMap<>();
/**
* 投票
* @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 voteManager = new VoteManager();
for(int i=0;i<8;i++) {
voteManager.vote("zhagnsan", "A");
}
}
}
存在问题:
一个问题是,如果现在修改某种投票情况所对应的具体功能处理,那就需要在那个大杂烩中,找到相应的代码块,然后进行改动。
第二个问题: 如果要添加新的功能,比如投票超过8次但不足10次的,给个机会,只是禁止登陆和使用系统3天,如果再犯,才永久封掉账号,该怎么办呢?那就需要改动投票管理的源代码。在上面的if-else 结构中再添加一个else if 块进行处理。
不管哪一种情况,都是在一大堆的控制代码中找出需要的部分,然后进行修改,这不是个好办法。那么该如何实现才能做到: 既能够很容易地给vote() 方法添加新的功能,又能够很方便地修改已有的功能处理呢?
3. 使用状态模式来实现 投票功能
/**
* 封装一个投票状态的行为
* @author Administrator
*
*/
public interface VoteState {
public void vote(String user, String voteItem, VoteManager voteManager);
}
/**
* 正常投票
* @author Administrator
*
*/
public class NormalVoteState implements VoteState {
@Override
public void vote(String user, String voteItem, VoteManager voteManager) {
//正常投票
voteManager.getMapVote().put(user, voteItem);
System.out.println("恭喜你获得投票资格!!!");
}
}
public class RepeatVoteState implements VoteState {
@Override
public void vote(String user, String voteItem, VoteManager voteManager) {
//重复投票
System.out.println("请不要重复投票!!!");
}
}
public class SpiteVoteState implements VoteState {
@Override
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 {
@Override
public void vote(String user, String voteItem, VoteManager voteManager) {
//黑名单
//记录黑名单中,禁止登陆系统了
System.out.println("进入黑名单,将禁止登陆和使用本系统!!!");
}
}
/**
* 投票管理
* @author Administrator
*
*/
public class VoteManager {
/**
* 持有状态处理对象
*/
private VoteState state = null;
/**
* 记录用户投票的结果,map<用户名称,投票的选项>
*/
private Map<String,String> mapVote = new HashMap<>();
/**
* 记录用户投票次数
*/
private Map<String,Integer> mapVoteCount = new HashMap<>();
public void vote(String user,String voteItem) {
//1:先为该用户增加投票的次数
mapVoteCount.computeIfAbsent(user, k->0);
Integer oldVoteCount = mapVoteCount.get(user);
oldVoteCount++;
mapVoteCount.put(user, oldVoteCount);
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);
}
public Map<String, String> getMapVote() {
return mapVote;
}
}
public class Client {
public static void main(String[] args) {
VoteManager voteManager = new VoteManager();
for(int i=0;i<8;i++) {
voteManager.vote("zhagnsan", "A");
}
}
}
4. 状态的维护和转换控制
- 一是在上下稳重。因为状态本身通常被实现为上下文对象的状态,因此可以在上下文进行状态维护,当然也就可以控制状态的转换了。前面的 投票的示例就是采用这种方式。
- 另外一个地方就是在状态的处理类中。当每个状态处理对象处理完自身状态所对应的功能后,可以根据需要指定后继状态,以便让应用能正确处理后续的请求。
代码示例:
/**
* 投票管理
* @author Administrator
*
*/
public class VoteManager {
/**
* 记录用户投票的结果,map<用户名称,投票的选项>
*/
private Map<String,VoteState> mapState = new HashMap<>();
/**
* 记录用户投票的结果,map<用户名称,投票的选项>
*/
private Map<String,String> mapVote = new HashMap<>();
/**
* 记录用户投票次数
*/
private Map<String,Integer> mapVoteCount = new HashMap<>();
public void vote(String user,String voteItem) {
//1:先为该用户增加投票的次数
mapVoteCount.computeIfAbsent(user, k->0);
Integer oldVoteCount = mapVoteCount.get(user);
oldVoteCount++;
mapVoteCount.put(user, oldVoteCount);
VoteState state = mapState.get(user);
if(state == null) {
state = new NormalVoteState();
}
//然后调转状态对象来进行相应的操作
state.vote(user, voteItem, this);
}
public Map<String, String> getMapVote() {
return mapVote;
}
public Map<String, VoteState> getMapState() {
return mapState;
}
public void setMapState(Map<String, VoteState> mapState) {
this.mapState = mapState;
}
public Map<String, Integer> getMapVoteCount() {
return mapVoteCount;
}
}
/**
* 正常投票
* @author Administrator
*
*/
public class NormalVoteState implements VoteState {
@Override
public void vote(String user, String voteItem, VoteManager voteManager) {
//正常投票
voteManager.getMapVote().put(user, voteItem);
System.out.println("恭喜你获得投票资格!!!");
//正常投票完成,维护下一个状态,同一个人再投就重复了
voteManager.getMapState().put(user, new RepeatVoteState());
}
}
public class RepeatVoteState implements VoteState {
@Override
public void vote(String user, String voteItem, VoteManager voteManager) {
//重复投票
System.out.println("请不要重复投票!!!");
//正常投票完成,维护下一个状态,重复投票到5次,就算恶意投票
if(voteManager.getMapVoteCount().get(user) >= 4) {
voteManager.getMapState().put(user, new SpiteVoteState());
}
}
}
public class SpiteVoteState implements VoteState {
@Override
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("你有恶意刷票行为,取消投票资格!!!");
//正常投票完成,维护下一个状态,重复投票到5次,就算恶意投票
if(voteManager.getMapVoteCount().get(user) >= 7) {
voteManager.getMapState().put(user, new BlackVoteState());
}
}
}
public class BlackVoteState implements VoteState {
@Override
public void vote(String user, String voteItem, VoteManager voteManager) {
//黑名单
//记录黑名单中,禁止登陆系统了
System.out.println("进入黑名单,将禁止登陆和使用本系统!!!");
}
}