設計模式-策略者模式

1、定義

    策略模式是針對一組算法,將每一個算法封裝到具備公共接口的獨立的類中,從而使它們能夠相互替換。策略模式使得算法能夠在不影響到客戶端的狀況下發生變化。算法

 

2、UML類圖

image

 

3、例子展現

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

4、項目中實際用到

咱們是作在線練習系統。其中有個功能模塊,判斷試題的對錯。對於不一樣的題型:單選、多選、判斷、填空、解答,判斷對錯的算法不一樣,可是本質都是要獲得這道題是否正確。ide

首先咱們能夠抽象出一個獲得對錯的算法接口,即策略者類:函數

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

 

接下來寫各類不一樣題型獲得對錯的類,具體策略者類:this

// 判斷選擇題的策略者

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

 

其餘題型再也不一一列舉。spa

 

和簡單工廠聯合,獲得具體策略者。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

 

具體應用上下文中,經過構造函數傳入工廠:blog

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

 

5、總結

策略者模式主要是對算法的封裝,把一系列算法封裝到策略者類中,從而能夠是不一樣的策略類自由切換並且避免了在代碼中寫不少if 或者switch。排序

相關文章
相關標籤/搜索