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("進入黑名單,將禁止登陸和使用本系統!!!");
}
}