zoukankan      html  css  js  c++  java
  • 设计模式-策略者模式

    一、定义

        策略模式是针对一组算法,将每个算法封装到具有公共接口的独立的类中,从而使它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

    二、UML类图

    image

    三、例子展示

    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);
            }
        }
    }
    View Code

    四、项目中实际用到

    我们是做在线练习系统。其中有个功能模块,判断试题的对错。对于不同的题型:单选、多选、判断、填空、解答,判断对错的算法不同,但是本质都是要得到这道题是否正确。

    首先我们可以抽象出一个得到对错的算法接口,即策略者类:

    public interface IJudgeCorrect<TDoQuestion>
    {
        bool DoJugeCorrect(TDoQuestion doQuestion);
    } 
    View Code

    接下来写各种不同题型得到对错的类,具体策略者类:

    // 判断选择题的策略者
    
    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();
        }
    } 
    View Code

    其他题型不再一一列举。

    和简单工厂联合,得到具体策略者。

    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;
            }
        }
    View Code

    具体应用上下文中,通过构造函数传入工厂:

    public SubmitStudyInfo(TDbContext dbContext, IJudgeCorrectFactory<Question, DoQuestion> jugeCorrectFactory)
           {
               _jugeCorrectFactory = jugeCorrectFactory;
               _dbContext = dbContext;
           } 
    View Code

    五、总结

    策略者模式主要是对算法的封装,把一系列算法封装到策略者类中,从而可以是不同的策略类自由切换而且避免了在代码中写很多if 或者switch。

  • 相关阅读:
    appscan的初步使用
    解决selenium自动化上传图片或文件出现windows窗口问题
    写入excel数据报错:ValueError: Cannot convert {'code': 0, 'msg': 'login success!', 'username': 'test',} to Excel
    接口自动化使用session会话解决数据依赖问题
    使用django开发一个简单的post接口
    windows10,解决jmeter5.2.1版本界面字体过小问题
    django配置使用mysql数据库运行报错:django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named 'MySQLdb'
    python装饰器
    python闭包
    工作总结
  • 原文地址:https://www.cnblogs.com/zh1990/p/6118280.html
Copyright © 2011-2022 走看看