首頁  >  文章  >  Java  >  Java中策略模式和範本方法模式的介紹(附程式碼)

Java中策略模式和範本方法模式的介紹(附程式碼)

不言
不言轉載
2019-02-19 15:56:372502瀏覽

這篇文章帶給大家的內容是關於Java中策略模式和範本方法模式的介紹(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

策略模式

簡介

策略模式(Strategy Pattern)屬於物件的行為模式。其用意是針對一組演算法,將每一個演算法封裝到具有共同介面的獨立的類別中,從而使得它們可以相互替換。策略模式使得演算法可以在不影響客戶端的情況下發生變化。
其主要目的是透過定義相似的演算法,取代if else 語句寫法,並且可以隨時相互替換。

策略模式主要由這三個角色組成,環境角色(Context)、抽象策略角色(Strategy)和具體策略角色(ConcreteStrategy)。

  • 環境角色(Context):持有一個策略類別的引用,提供給客戶端使用。

  • 抽象策略角色(Strategy):這是一個抽象角色,通常由一個介面或抽象類別實作。此角色給出所有的具體策略類別所需的介面。

  • 具體策略角色(ConcreteStrategy):包裝了相關的演算法或行為。

範例圖如下:
Java中策略模式和範本方法模式的介紹(附程式碼)

這裡為了方便理解,我們就拿剛學習Java的時候使用計算方法來說吧。
在使用計算機進行計算的時候,會常用到加減乘除方法。如果我們想要得到兩個數字相加的和,我們需要用到「 」符號,得到相減的差,需要用到「-」符號等等。雖然我們可以透過字串比較使用if/else寫成通用方法,但是計算的符號每次增加,我們就不得不加在原先的方法中進行增加相應的程式碼,如果後續計算方法增加、修改或刪除,那麼會使後續的維護變得困難。
但是在這些方法中,我們發現其基本方法是固定的,這時我們就可以透過策略模式來進行開發,可以有效避免透過if/else來進行判斷,即使後續增加其他的計算規則也可靈活進行調整。

先定義一個抽象策略角色,並且擁有一個計算的方法。

interface CalculateStrategy {
   int doOperation(int num1, int num2);
}

然後再定義加減乘除這些具體策略角色並實作方法。

那麼程式碼如下:

class OperationAdd implements CalculateStrategy {
   @Override   public int doOperation(int num1, int num2) {
          return num1 + num2;
   }
}
class OperationSub implements CalculateStrategy {
   @Override   public int doOperation(int num1, int num2) {
          return num1 - num2;
   }
}
class OperationMul implements CalculateStrategy {
   @Override   public int doOperation(int num1, int num2) {
          return num1 * num2;
   }
}
class Operationp implements CalculateStrategy {
   @Override   public int doOperation(int num1, int num2) {
          return num1 / num2;
   }
}

最後在定義一個環境角色,提供一個計算的介面供客戶端使用。
程式碼如下:

class  CalculatorContext {
    private CalculateStrategy strategy;
    public CalculatorContext(CalculateStrategy strategy) {
            this.strategy = strategy;
    }    
    public int executeStrategy(int num1, int num2) {
            return strategy.doOperation(num1, num2);
    }
}

寫好之後,那麼我們來進行測試。
測試程式碼如下:

    public static void main(String[] args) {
          int a=4,b=2;
          CalculatorContext context = new CalculatorContext(new OperationAdd());    
          System.out.println("a + b = "+context.executeStrategy(a, b));
     
          CalculatorContext context2 = new CalculatorContext(new OperationSub());      
          System.out.println("a - b = "+context2.executeStrategy(a, b));
     
          CalculatorContext context3 = new CalculatorContext(new OperationMul());    
          System.out.println("a * b = "+context3.executeStrategy(a, b));
    
          CalculatorContext context4 = new CalculatorContext(new Operationp());    
          System.out.println("a / b = "+context4.executeStrategy(a, b));
}

輸出結果:

a + b = 6
a - b = 2
a * b = 8
a / b = 2

策略模式優點:

擴展性好,可以在不修改物件結構的情況下,為新的演算法進行添加新的類別進行實現;
靈活性好,可以對演算法進行自由切換;

策略模式缺點:

使用策略類別變多,會增加系統的複雜度。 ;
客戶端必須知道所有的策略類別才能進行呼叫;

使用場景:

#如果在一個系統裡面有許多類,它們之間的區別僅在於它們的行為,那麼使用策略模式可以動態地讓一個物件在許多行為中選擇一種行為;
#一個系統需要動態地在幾個演算法中選擇一種;
如果一個物件有很多的行為,如果不用恰當的模式,這些行為就只好使用多重的條件來選擇語句來實現;

模板模式

簡介

模板模式(Template Pattern)中,一個抽象類公開定義了執行它的方法的方式/模板。它的子類別可以按需要重寫方法實現,但呼叫將以抽象類別中定義的方式進行。這種類型的設計模式屬於行為型模式。定義一個操作中的演算法的骨架,而將一些步驟延遲到子類別。

模板模式,其主要的想法就是做一個模板,提供給客戶端進行呼叫。除去生活中我們常用到的履歷範本、合約範本等等,Java中也有很經典的範本使用,那就是Servlet,HttpService類別提供了一個service()方法,這個方法呼叫七個do方法中的一個或幾個,完成對客戶端呼叫的回應。這些do方法需要由HttpServlet的具體則由子類別提供。

模板模式主要由抽像模板(Abstract Template)角色和具體模板(Concrete Template)角色組成。

  • 抽象模板(Abstract Template): 定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤;定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。

  • 具体模板(Concrete Template): 实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤;每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。

示例图如下:
Java中策略模式和範本方法模式的介紹(附程式碼)

这里为了方便理解,我们依旧使用一个简单的示例来加以说明。
我们以前在玩魂斗罗、双截龙、热血物语、忍者神龟等等游戏的时候,都需要在小霸王游戏机上插卡,然后启动游戏才能玩,其中魂斗罗这种游戏,启动游戏之后就可以直接玩了,但是忍者神龟这种游戏则在启动游戏之后,需要选择其中一个角色才能开始玩。那么我们可以根据这个场景写出一个通用的模板,主要包含启动游戏,玩游戏,结束游戏这几个必须实现的方法,选择人物这个方法改成可选。

那么这个抽象类的代码如下:

abstract class  Game{    
    //启动游戏    
    protected abstract void  runGame();    
    //选择人物    
    protected  void choosePerson() {};    
    //开始玩游戏    
    protected abstract void startPlayGame();    
    //结束游戏    
    protected abstract void endPlayGame();    
    //模板方法    
    public final void play() {
        runGame();
        choosePerson();
        startPlayGame();
        endPlayGame();
    }
    
}

定义好该抽象类之后,我们再来定义具体模板实现类。这里定义两个游戏类,一个是魂斗罗,一个忍者神龟。

那么代码如下:

class ContraGame extends Game{   @Override   protected void runGame() {
       System.out.println("启动魂斗罗II...");
   }   
@Override   protected void startPlayGame() {
          System.out.println("1P正在使用S弹打aircraft...");
   }   
@Override   protected void endPlayGame() {
          System.out.println("1P被流弹打死了,游戏结束!");
   }
}
class TMNTGame extends Game{
   @Override   protected void runGame() { 
         System.out.println("启动忍者神龟III...");
   }   
   @Override   protected void choosePerson() {       System.out.println("1P选择了Raph !");
   }   
   @Override   protected void startPlayGame() {
          System.out.println("Raph正在使用绝技 “火箭头槌” ");
   }   
   @Override   protected void endPlayGame() {
          System.out.println("Raph 掉进井盖里死了,游戏结束了! ");
   }
}

最后再来进行测试,测试代码如下:

public static void main(String[] args) {
       Game game = new ContraGame();
       game.play();
       System.out.println();
       game = new TMNTGame();
       game.play();

}

输出结果:

启动魂斗罗II...1P正在使用S弹打aircraft...1P被流弹打死了,游戏结束!

启动忍者神龟III...1P选择了Raph !
Raph正在使用绝技 “火箭头槌” 
Raph 掉进井盖里死了,游戏结束了!

模板模式优点:

扩展性好,对不变的代码进行封装,对可变的进行扩展;
可维护性好,因为将公共代码进行了提取,使用的时候直接调用即可;

模板模式缺点:

因为每一个不同的实现都需要一个子类来实现,导致类的个数增加,会使系统变得复杂;

使用场景:

有多个子类共有逻辑相同的方法;
重要的、复杂的方法,可以考虑作为模板方法。

注意事项:

为防止恶意操作,一般模板方法都加上 final 关键词!

以上是Java中策略模式和範本方法模式的介紹(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除