前言
如何增加代码行数,设计模式应该是一个不错的选择。后续设计模式的内容会持续更新,欢迎关注。
语言使用的是C#,纯面向对象的语言。笔者比较喜欢C#,C#的语法糖和设计都很棒,其他语言同理,语言只是工具。
设计模式的目的
增加代码量是最不重要的目的,其真正的目的是符合软件设计原则:
- 开闭原则
- 依赖倒置原则
- 接口隔离原则
- 单一职责原则
其中的开闭原则是最重要的,大部分的设计模式也在解决这个问题。
不用设计模式
设计一个投票系统。要求如下:
- 投票一次,表示投票成功
- 投票在3次以内,提示不要重复投票
- 3次到7次,为恶意投票,删除用户
- 超过8次(含),加入黑名单,禁止登陆系统。
代码实现
代码很简单。判断投票数,对不同状态的处理。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class VoteManager
{
private Dictionary<String, String> dictionaryVote = new Dictionary<string, string>();
private Dictionary<String, int> dictionaryVoteCount = new Dictionary<string, int>();
private int count = 0;
public void Vote(String user, String voteItem)
{
bool contain = dictionaryVoteCount.ContainsKey(user);
if (!contain)
{
dictionaryVoteCount[user] = 0;
}
count = dictionaryVoteCount[user] + 1;
dictionaryVoteCount[user] = count;
if (count == 1)
{
Console.WriteLine("投票成功");
dictionaryVote.Add(user, voteItem);
} else if(count > 1 && count < 3) {
Console.WriteLine("请不要重复投票");
} else if (count >= 3 && count < 8) {
dictionaryVote.Remove(user);
Console.WriteLine("存在恶意投票行为,取消投票资格");
} else if (count >= 8) {
Console.WriteLine("加入黑名单,禁止登陆系统");
}
}
}
}
代码存在的问题
- 代码量好像有点少
- 大量的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 int count = 0;
public Dictionary<String, String> getDictionaryVote()
{
return dictionaryVote;
}
public void Vote(String user, String item)
{
bool contain = dictionaryVoteCount.ContainsKey(user);
if (!contain)
{
dictionaryVoteCount[user] = 0;
}
count = dictionaryVoteCount[user] + 1;
dictionaryVoteCount[user] = count;
//状态处理
if (count == 1)
{
voteState = new NormalVoteState();
} else if(count > 1 && count< 3) {
voteState = new RepeatNoteState();
} else if (count >= 3 && count< 8) {
voteState = new SpiteVoteState();
} else if (count >= 8) {
voteState = new BlackVoteState();
}
voteState.Vote(user, item, this);
}
}
}
状态接口
namespace ConsoleApp1
{
internal interface VoteState
{
public void Vote(string user, string item, VoteManagerContext voteManagerContext);
}
}
具体实现
正常投票状态
namespace ConsoleApp1
{
internal class NormalVoteState : VoteState
{
public void Vote(string user, string item, VoteManagerContext voteManagerContext)
{
Console.WriteLine("投票成功");
voteManagerContext.getDictionaryVote().Add(user, item);
}
}
}
重复投票状态
namespace ConsoleApp1
{
internal class RepeatNoteState : VoteState
{
public void Vote(string user, string item, VoteManagerContext voteManagerContext)
{
Console.WriteLine("请不要重复投票");
}
}
}
恶意投票状态
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("存在恶意投票行为,取消投票资格");
}
}
}
黑名单投票状态
namespace ConsoleApp1
{
internal class BlackVoteState : VoteState
{
public void Vote(string user, string item, VoteManagerContext voteManagerContext)
{
Console.WriteLine("加入黑名单,禁止登陆系统");
}
}
}
客户端代码
using ConsoleApp1;
public class ConsoleApp
{
public static void Main(String[] atgs)
{
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没有被消灭,可有办法解决哪?下一篇文章来彻底消灭if/else。
写在最后
本文的Java版本可参考设计模式之状态模式。
设计模式,讲究面向接口而不是具体的实现。
公众号
更多内容,欢迎关注我的微信公众号: 无情剑客。