在设计模式之状态模式中对状态模式进行了介绍,留下了一个悬念,如何彻底干掉if/else。本文主要解决这个问题。
状态转化和维护
在上一篇文章中,状态的维护在上下文中,这就不可避免的使用到if/else进行判断。如果把状态的维护放在状态的处理类中,那就可以避免大连的if/else使用了。
状态处理类中维护状态: 当每一个状态对象处理完自身的状态所对应的功能喉,咳哟根据需要指定后继的状态,以便让应用能够正确处理后续的请求。
时序图
类图和上面的文章一样,主要看时序图,能够很方便理解上面的内容。
恶意投票状态和黑名单状态于这个类似,时序图中没有画出。
代码实现
客户端代码
先看客户端,使用模式和没有使用模式进行对比,没有使用模式的实现在设计模式之状态模式。
Console.WriteLine("不用模式的运行结果:");
VoteManager voteManager = new VoteManager();
for (int i = 0; i < 10; i++)
{
voteManager.Vote("Burning", "sxy");
}
Console.WriteLine("\n");
Console.WriteLine("使用状态模式的运行结果:");
VoteManagerContext vmc = new VoteManagerContext();
for (int i = 0; i < 10; i++)
{
vmc.Vote("Burning", "sxy");
}
上下文实现
由于把状态的维护放在了状态处理类中,上下文没有的大连的if/else。主要增加了用户状态类字典,方便状态维护。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class VoteManagerContext
{
// 投票状态
private VoteState voteState;
// 投票用户 投票选项
private Dictionary<String, String> dictionaryVote = new Dictionary<String, String>();
// 投票用户 投票数量
private Dictionary<String, int> dictionaryVoteCount = new Dictionary<string, int>();
// 投票用户 状态
private Dictionary<String, VoteState> dictionaryVoteState = new Dictionary<string, VoteState>();
//保存投票的数量
private int count = 0;
public Dictionary<String, String> getDictionaryVote()
{
return dictionaryVote;
}
public Dictionary<String, VoteState> getDictionaryVoteState()
{
return dictionaryVoteState;
}
public Dictionary<String, int> getDictionaryVoteCount()
{
return dictionaryVoteCount;
}
public void Vote(String user, String item)
{
bool contain = dictionaryVoteState.ContainsKey(user);
if (!contain)
{
voteState = new NormalVoteState();
dictionaryVoteState.Add(user, voteState);
}
voteState = dictionaryVoteState[user];
count = count + 1;
if (!dictionaryVoteCount.ContainsKey(user))
{
dictionaryVoteCount.Add(user, count);
}
dictionaryVoteCount[user] = count;
voteState.Vote(user, item, this);
}
}
}
正常投票状态
添加后续状态(重复投票)的维护。
namespace ConsoleApp1
{
internal class NormalVoteState : VoteState
{
public void Vote(string user, string item, VoteManagerContext voteManagerContext)
{
Console.WriteLine("投票成功");
Dictionary<String, int> dictionaryVoteCount = voteManagerContext.getDictionaryVoteCount();
if (dictionaryVoteCount[user] == 1)
{
voteManagerContext.getDictionaryVote().Add(user, item);
}
Dictionary<String, int> voteCount = voteManagerContext.getDictionaryVoteCount();
if (voteCount[user] < 3)
{
voteManagerContext.getDictionaryVoteState()[user] = new RepeatNoteState();
}
}
}
}
重复投票状态
添加后续状态(恶意投票)的维护。
namespace ConsoleApp1
{
internal class RepeatNoteState : VoteState
{
public void Vote(string user, string item, VoteManagerContext voteManagerContext)
{
Console.WriteLine("请不要重复投票");
Dictionary<String, int> voteCount = voteManagerContext.getDictionaryVoteCount();
if (voteCount[user] < 8)
{
voteManagerContext.getDictionaryVoteState()[user] = new SpiteVoteState();
}
}
}
}
恶意投票状态
添加后续状态(黑名单)的维护。
namespace ConsoleApp1
{
internal class SpiteVoteState : VoteState
{
public void Vote(string user, string item, VoteManagerContext voteManagerContext)
{
bool contain = voteManagerContext.getDictionaryVote().ContainsKey(user);
if (contain)
{
voteManagerContext.getDictionaryVote().Remove(user);
}
Console.WriteLine("存在恶意投票行为,取消投票资格");
Dictionary<String, int> voteCount = voteManagerContext.getDictionaryVoteCount();
if (voteCount[user] >= 7)
{
voteManagerContext.getDictionaryVoteState()[user] = new BlackVoteState();
}
}
}
}
黑名单状态
不需要添加后续状态维护。
namespace ConsoleApp1
{
internal class BlackVoteState : VoteState
{
public void Vote(string user, string item, VoteManagerContext voteManagerContext)
{
Console.WriteLine("加入黑名单,禁止登陆系统");
}
}
}
运行结果
完全相同,代码量增加了很多,同时避免的大连的if/else条件判断。
扩展
8到9次,给个机会,禁止3天内登陆系统。添加相应的类,修改以下前面的状态类的后继状态即可。这里主要是新添加的类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class BlackVWarnoteState : VoteState
{
public void Vote(string user, string item, VoteManagerContext voteManagerContext)
{
bool contain = voteManagerContext.getDictionaryVote().ContainsKey(user);
if (contain)
{
voteManagerContext.getDictionaryVote().Remove(user);
}
Console.WriteLine("禁止3天内登陆系统");
Dictionary<String, int> voteCount = voteManagerContext.getDictionaryVoteCount();
if (voteCount[user] >= 9)
{
voteManagerContext.getDictionaryVoteState()[user] = new BlackVoteState();
}
}
}
}
运行结果
本质
根据状态来分离和选择行为
下载最后
通过工厂+状态也能够实现消灭if/else,并且更加完美。
公众号