设计模式-策略者模式
一、定义
策略模式是针对一组算法,将每个算法封装到具有公共接口的独立的类中,从而使它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
二、UML类图
三、例子展示
namespace 策略者模式 { public interface ITaxStrategy { double GetTax(double money); } public class PersnalStrategy : ITaxStrategy { public double GetTax(double money) { return money * 0.1; } } public class EnterpriseTaxStrategy : ITaxStrategy { public double GetTax(double money) { return (money - 4000) > 0 ? (money - 4000) * 0.045 : 0.0; } } public class TaxContext { private ITaxStrategy _strategy; public TaxContext(ITaxStrategy taxStrategy) { _strategy = taxStrategy; } public double GetTax(double money) { return _strategy.GetTax(money); } } public class Client { public static void Process() { TaxContext taxContext = new TaxContext(new PersnalStrategy()); double tax = taxContext.GetTax(10000); Console.WriteLine("个人所得税:"+tax); taxContext = new TaxContext(new EnterpriseTaxStrategy()); tax = taxContext.GetTax(100000); Console.WriteLine("企业所得税:" + tax); // 与简单工厂模式一起,避免客户端既依赖于TaxContext,又依赖于具体策略者。这样客户端只需要知道TaxContext就可以了 TaxContext2 taxContext2 = new TaxContext2("PersnalStrategy"); double tax2 = taxContext2.GetTax(10000); Console.WriteLine("升级版 个人所得税:" + tax2); taxContext2 = new TaxContext2("EnterpriseTaxStrategy"); tax2 = taxContext2.GetTax(100000); Console.WriteLine("升级版 企业所得税:" + tax2); } } public class TaxContext2 { private ITaxStrategy _strategy; /// <summary> /// 简单工厂一起 /// </summary> /// <param name="taxType"></param> public TaxContext2(string taxType) { switch (taxType) { case "PersnalStrategy": _strategy = new PersnalStrategy(); break; case "EnterpriseTaxStrategy": _strategy = new EnterpriseTaxStrategy(); break; default: break; } } public double GetTax(double money) { return _strategy.GetTax(money); } } }
四、项目中实际用到
我们是做在线练习系统。其中有个功能模块,判断试题的对错。对于不同的题型:单选、多选、判断、填空、解答,判断对错的算法不同,但是本质都是要得到这道题是否正确。
首先我们可以抽象出一个得到对错的算法接口,即策略者类:
public interface IJudgeCorrect<TDoQuestion> { bool DoJugeCorrect(TDoQuestion doQuestion); }
接下来写各种不同题型得到对错的类,具体策略者类:
// 判断选择题的策略者 public class JudgeChoiceQuestionCorrect : IJudgeCorrect<DoQuestion> { public bool DoJugeCorrect(DoQuestion doQuestion) { if (string.IsNullOrEmpty(doQuestion.Answer)) { return false; } // 对Answer按照abcd的顺序排序,有可能从前台传来的数据不对 if (doQuestion.Answer.Length > 1) { var answerarray = doQuestion.Answer.ToCharArray().OrderBy(p => p).ToArray(); doQuestion.Answer = new string(answerarray); } return doQuestion.Question.Answer.Trim() == doQuestion.Answer.Trim(); } } // 判断题策略者类 public class JudgeTrueFalseQuestionCorrect : IJudgeCorrect<DoQuestion> { public bool DoJugeCorrect(DoQuestion doQuestion) { if (string.IsNullOrEmpty(doQuestion.Answer)) { return false; } return doQuestion.Question.Answer.Trim() == doQuestion.Answer.Trim(); } }
其他题型不再一一列举。
和简单工厂联合,得到具体策略者。
public class JudgeCorrectFactory : IJudgeCorrectFactory<Question,DoQuestion> { private Dictionary<QuestionMode, IJudgeCorrect<DoQuestion>> _factoties = new Dictionary<QuestionMode, IJudgeCorrect<DoQuestion>>(); public IJudgeCorrect<DoQuestion> CreateJudgeCorrect(Question question) { IJudgeCorrect<DoQuestion> jugeCorrect = null ; switch (question.QuestionMode) { case QuestionMode.SingleChoice: case QuestionMode.DoubleChoice: case QuestionMode.MultipleChoice: if (_factoties.Keys.Contains(QuestionMode.SingleChoice)) { jugeCorrect = _factoties[QuestionMode.SingleChoice]; } else { jugeCorrect = new JudgeChoiceQuestionCorrect(); _factoties.Add(QuestionMode.SingleChoice, jugeCorrect); } break; case QuestionMode.TrueFalse: if (_factoties.Keys.Contains(QuestionMode.TrueFalse)) { jugeCorrect = _factoties[QuestionMode.TrueFalse]; } else { jugeCorrect = new JudgeTrueFalseQuestionCorrect(); _factoties.Add(QuestionMode.TrueFalse, jugeCorrect); } break; case QuestionMode.FillBlank: if (_factoties.Keys.Contains(QuestionMode.FillBlank)) { jugeCorrect = _factoties[QuestionMode.FillBlank]; } else { jugeCorrect = new JudgeFillBlankQuestionCorrect(); _factoties.Add(QuestionMode.FillBlank, jugeCorrect); } break; case QuestionMode.Discuss: if (_factoties.Keys.Contains(QuestionMode.Discuss)) { jugeCorrect = _factoties[QuestionMode.Discuss]; } else { jugeCorrect = new JudgeDiscussQuestionCorrect(); _factoties.Add(QuestionMode.Discuss, jugeCorrect); } break; case QuestionMode.Complex: if (_factoties.Keys.Contains(QuestionMode.Complex)) { jugeCorrect = _factoties[QuestionMode.Complex]; } else { jugeCorrect = new JudgeComplexQuestionCorrect(this); _factoties.Add(QuestionMode.Complex, jugeCorrect); } break; default: throw new Exception("获取判断试卷参数错误!"); } return jugeCorrect; } }
具体应用上下文中,通过构造函数传入工厂:
public SubmitStudyInfo(TDbContext dbContext, IJudgeCorrectFactory<Question, DoQuestion> jugeCorrectFactory) { _jugeCorrectFactory = jugeCorrectFactory; _dbContext = dbContext; }
五、总结
策略者模式主要是对算法的封装,把一系列算法封装到策略者类中,从而可以是不同的策略类自由切换而且避免了在代码中写很多if 或者switch。