設計模式--策略模式Strategy

策略模式

演算法經常需要被改變==使用S

節省資源(很多if else if….不會被執行,卻會被裝載到程式碼段)

  • 動機

    • 在軟體構建過程中,某些對象使用的演算法可能多種多樣,經常改變,如果將這些演算法都編碼到對象中,將會使對象變得異常複雜;而且有時候支援不使用的演算法也是一個性能負擔。
    • 如何在運行時根據需要透明地更改對象的演算法?將演算法與對象本身解耦,從而避免上述問題?
  • 定義:

    • 定義一系列演算法,把它們一個個封裝起來,並且使它們可互相替換(變化)。該模式使得演算法可獨立於使用它的客戶程式(穩定)而變化(擴展,子類化)。

      image-20211109122723168

  • 程式碼對比

    • 無strategy模式:(使用if else):請放在時間軸,看未來需要添加的東西,需要修改!!!不符合開閉原則

      enum TaxBase {
      	CN_Tax,
      	US_Tax,
      	DE_Tax,
      	FR_Tax       //¸ü¸Ä
      };
      
      class SalesOrder{
          TaxBase tax;
      public:
          double CalculateTax(){
              //...
              
              if (tax == CN_Tax){
                  //CN***********
              }
              else if (tax == US_Tax){
                  //US***********
              }
              else if (tax == DE_Tax){
                  //DE***********
              }
      		else if (tax == FR_Tax){  //¸ü¸Ä
      			//...
      		}
      
              //....
           }
          
      };
      
    • 使用strategy模式

      • SalesOrder和Strategy是穩定的 不用變化,只需要擴展
      //文件TaxStrategy.cpp
      class TaxStrategy{
      public:
          virtual double Calculate(const Context& context)=0;
          virtual ~TaxStrategy(){}
      };
      
      //文件2 CNTax.cpp
      class CNTax : public TaxStrategy{
      public:
          virtual double Calculate(const Context& context){
              //***********
          }
      };
      //文件3
      class USTax : public TaxStrategy{
      public:
          virtual double Calculate(const Context& context){
              //***********
          }
      };
      //文件四
      class DETax : public TaxStrategy{
      public:
          virtual double Calculate(const Context& context){
              //***********
          }
      };
      
      
      
      //新擴展的文件(沒有對之前的文件進行修改
      //*********************************
      class FRTax : public TaxStrategy{
      public:
      	virtual double Calculate(const Context& context){
      		//.........
      	}
      };
      
      
      //文件 SalesOrder.cpp
      class SalesOrder{
      private:
          TaxStrategy* strategy;
      
      public:
          SalesOrder(StrategyFactory* strategyFactory){
              this->strategy = strategyFactory->NewStrategy();
          }
          ~SalesOrder(){
              delete this->strategy;
          }
      
          public double CalculateTax(){
              //...
              Context context();
              
              double val = 
                  strategy->Calculate(context); //¶à̬µ÷ÓÃ
              //...
          }
          
      };
      
  • 總結:

    • Strategy及其子類為組件提供了一系列可重用的演算法,從而可以使得類型在運行時方便地根據需要在各個演算法之間進行切換
    • Strategy模式提供了用條件判斷語句以外的另一種選擇,消除條件判斷語句,就是在解耦合。含有許多條件判斷語句的程式碼通常都需要Strategy模式。