Java中策略模式和模板方法模式的案例分析-創(chuàng)新互聯(lián)

小編給大家分享一下Java中策略模式和模板方法模式的案例分析,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!

建網(wǎng)站原本是網(wǎng)站策劃師、網(wǎng)絡(luò)程序員、網(wǎng)頁(yè)設(shè)計(jì)師等,應(yīng)用各種網(wǎng)絡(luò)程序開(kāi)發(fā)技術(shù)和網(wǎng)頁(yè)設(shè)計(jì)技術(shù)配合操作的協(xié)同工作。創(chuàng)新互聯(lián)專(zhuān)業(yè)提供網(wǎng)站制作、成都做網(wǎng)站,網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站制作(企業(yè)站、自適應(yīng)網(wǎng)站建設(shè)、電商門(mén)戶網(wǎng)站)等服務(wù),從網(wǎng)站深度策劃、搜索引擎友好度優(yōu)化到用戶體驗(yàn)的提升,我們力求做到極致!

策略模式

簡(jiǎn)介

策略模式(Strategy Pattern)屬于對(duì)象的行為模式。其用意是針對(duì)一組算法,將每一個(gè)算法封裝到具有共同接口的獨(dú)立的類(lèi)中,從而使得它們可以相互替換。策略模式使得算法可以在不影響到客戶端的情況下發(fā)生變化。
其主要目的是通過(guò)定義相似的算法,替換if else 語(yǔ)句寫(xiě)法,并且可以隨時(shí)相互替換。

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

  • 環(huán)境角色(Context):持有一個(gè)策略類(lèi)的引用,提供給客戶端使用。

  • 抽象策略角色(Strategy):這是一個(gè)抽象角色,通常由一個(gè)接口或抽象類(lèi)實(shí)現(xiàn)。此角色給出所有的具體策略類(lèi)所需的接口。

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

示例圖如下:
Java中策略模式和模板方法模式的案例分析

這里為了方便理解,我們就拿剛學(xué)習(xí)Java的時(shí)候使用計(jì)算方法來(lái)說(shuō)吧。
在使用計(jì)算器進(jìn)行計(jì)算的時(shí)候,會(huì)經(jīng)常用到加減乘除方法。如果我們想得到兩個(gè)數(shù)字相加的和,我們需要用到“+”符號(hào),得到相減的差,需要用到“-”符號(hào)等等。雖然我們可以通過(guò)字符串比較使用if/else寫(xiě)成通用方法,但是計(jì)算的符號(hào)每次增加,我們就不得不加在原先的方法中進(jìn)行增加相應(yīng)的代碼,如果后續(xù)計(jì)算方法增加、修改或刪除,那么會(huì)使后續(xù)的維護(hù)變得困難。
但是在這些方法中,我們發(fā)現(xiàn)其基本方法是固定的,這時(shí)我們就可以通過(guò)策略模式來(lái)進(jìn)行開(kāi)發(fā),可以有效避免通過(guò)if/else來(lái)進(jìn)行判斷,即使后續(xù)增加其他的計(jì)算規(guī)則也可靈活進(jìn)行調(diào)整。

首先定義一個(gè)抽象策略角色,并擁有一個(gè)計(jì)算的方法。

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

然后再定義加減乘除這些具體策略角色并實(shí)現(xiàn)方法。

那么代碼如下:

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

最后在定義一個(gè)環(huán)境角色,提供一個(gè)計(jì)算的接口供客戶端使用。
代碼如下:

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

編寫(xiě)好之后,那么我們來(lái)進(jìn)行測(cè)試。
測(cè)試代碼如下:

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

輸出結(jié)果:

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

策略模式優(yōu)點(diǎn):

擴(kuò)展性好,可以在不修改對(duì)象結(jié)構(gòu)的情況下,為新的算法進(jìn)行添加新的類(lèi)進(jìn)行實(shí)現(xiàn);
靈活性好,可以對(duì)算法進(jìn)行自由切換;

策略模式缺點(diǎn):

使用策略類(lèi)變多,會(huì)增加系統(tǒng)的復(fù)雜度。;
客戶端必須知道所有的策略類(lèi)才能進(jìn)行調(diào)用;

使用場(chǎng)景:

如果在一個(gè)系統(tǒng)里面有許多類(lèi),它們之間的區(qū)別僅在于它們的行為,那么使用策略模式可以動(dòng)態(tài)地讓一個(gè)對(duì)象在許多行為中選擇一種行為;
一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種;
如果一個(gè)對(duì)象有很多的行為,如果不用恰當(dāng)?shù)哪J?,這些行為就只好使用多重的條件選擇語(yǔ)句來(lái)實(shí)現(xiàn);

模板模式

簡(jiǎn)介

模板模式(Template Pattern)中,一個(gè)抽象類(lèi)公開(kāi)定義了執(zhí)行它的方法的方式/模板。它的子類(lèi)可以按需要重寫(xiě)方法實(shí)現(xiàn),但調(diào)用將以抽象類(lèi)中定義的方式進(jìn)行。 這種類(lèi)型的設(shè)計(jì)模式屬于行為型模式。定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類(lèi)中。

模板模式,其主要的的思想就是做一個(gè)模板,提供給客戶端進(jìn)行調(diào)用。除去生活中我們經(jīng)常用到的簡(jiǎn)歷模板、合同模板等等,Java中也有很經(jīng)典的模板使用,那就是Servlet,HttpService類(lèi)提供了一個(gè)service()方法,這個(gè)方法調(diào)用七個(gè)do方法中的一個(gè)或幾個(gè),完成對(duì)客戶端調(diào)用的響應(yīng)。這些do方法需要由HttpServlet的具體則由子類(lèi)提供。

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

  • 抽象模板(Abstract Template): 定義了一個(gè)或多個(gè)抽象操作,以便讓子類(lèi)實(shí)現(xiàn)。這些抽象操作叫做基本操作,它們是一個(gè)頂級(jí)邏輯的組成步驟;定義并實(shí)現(xiàn)了一個(gè)模板方法。這個(gè)模板方法一般是一個(gè)具體方法,它給出了一個(gè)頂級(jí)邏輯的骨架,而邏輯的組成步驟在相應(yīng)的抽象操作中,推遲到子類(lèi)實(shí)現(xiàn)。頂級(jí)邏輯也有可能調(diào)用一些具體方法。

  • 具體模板(Concrete Template): 實(shí)現(xiàn)父類(lèi)所定義的一個(gè)或多個(gè)抽象方法,它們是一個(gè)頂級(jí)邏輯的組成步驟;每一個(gè)抽象模板角色都可以有任意多個(gè)具體模板角色與之對(duì)應(yīng),而每一個(gè)具體模板角色都可以給出這些抽象方法(也就是頂級(jí)邏輯的組成步驟)的不同實(shí)現(xiàn),從而使得頂級(jí)邏輯的實(shí)現(xiàn)各不相同。

示例圖如下:
Java中策略模式和模板方法模式的案例分析

這里為了方便理解,我們依舊使用一個(gè)簡(jiǎn)單的示例來(lái)加以說(shuō)明。
我們以前在玩魂斗羅、雙截龍、熱血物語(yǔ)、忍者神龜?shù)鹊扔螒虻臅r(shí)候,都需要在小霸王游戲機(jī)上插卡,然后啟動(dòng)游戲才能玩,其中魂斗羅這種游戲,啟動(dòng)游戲之后就可以直接玩了,但是忍者神龜這種游戲則在啟動(dòng)游戲之后,需要選擇其中一個(gè)角色才能開(kāi)始玩。那么我們可以根據(jù)這個(gè)場(chǎng)景寫(xiě)出一個(gè)通用的模板,主要包含啟動(dòng)游戲,玩游戲,結(jié)束游戲這幾個(gè)必須實(shí)現(xiàn)的方法,選擇人物這個(gè)方法改成可選。

那么這個(gè)抽象類(lèi)的代碼如下:

abstract class  Game{    
    //啟動(dòng)游戲    
    protected abstract void  runGame();    
    //選擇人物    
    protected  void choosePerson() {};    
    //開(kāi)始玩游戲    
    protected abstract void startPlayGame();    
    //結(jié)束游戲    
    protected abstract void endPlayGame();    
    //模板方法    
    public final void play() {
        runGame();
        choosePerson();
        startPlayGame();
        endPlayGame();
    }
    
}

定義好該抽象類(lèi)之后,我們?cè)賮?lái)定義具體模板實(shí)現(xiàn)類(lèi)。這里定義兩個(gè)游戲類(lèi),一個(gè)是魂斗羅,一個(gè)忍者神龜。

那么代碼如下:

class ContraGame extends Game{   @Override   protected void runGame() {
       System.out.println("啟動(dòng)魂斗羅II...");
   }   
@Override   protected void startPlayGame() {
          System.out.println("1P正在使用S彈打aircraft...");
   }   
@Override   protected void endPlayGame() {
          System.out.println("1P被流彈打死了,游戲結(jié)束!");
   }
}
class TMNTGame extends Game{
   @Override   protected void runGame() { 
         System.out.println("啟動(dòng)忍者神龜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 掉進(jìn)井蓋里死了,游戲結(jié)束了! ");
   }
}

最后再來(lái)進(jìn)行測(cè)試,測(cè)試代碼如下:

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

}

輸出結(jié)果:

啟動(dòng)魂斗羅II...1P正在使用S彈打aircraft...1P被流彈打死了,游戲結(jié)束!

啟動(dòng)忍者神龜III...1P選擇了Raph !
Raph正在使用絕技 “火箭頭槌” 
Raph 掉進(jìn)井蓋里死了,游戲結(jié)束了!

模板模式優(yōu)點(diǎn):

擴(kuò)展性好,對(duì)不變的代碼進(jìn)行封裝,對(duì)可變的進(jìn)行擴(kuò)展;
可維護(hù)性好,因?yàn)閷⒐泊a進(jìn)行了提取,使用的時(shí)候直接調(diào)用即可;

模板模式缺點(diǎn):

因?yàn)槊恳粋€(gè)不同的實(shí)現(xiàn)都需要一個(gè)子類(lèi)來(lái)實(shí)現(xiàn),導(dǎo)致類(lèi)的個(gè)數(shù)增加,會(huì)使系統(tǒng)變得復(fù)雜;

使用場(chǎng)景:

有多個(gè)子類(lèi)共有邏輯相同的方法;
重要的、復(fù)雜的方法,可以考慮作為模板方法。

注意事項(xiàng):

為防止惡意操作,一般模板方法都加上 final 關(guān)鍵詞!

看完了這篇文章,相信你對(duì)Java中策略模式和模板方法模式的案例分析有了一定的了解,想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

網(wǎng)站題目:Java中策略模式和模板方法模式的案例分析-創(chuàng)新互聯(lián)
鏈接URL:http://bm7419.com/article0/iijoo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號(hào)、小程序開(kāi)發(fā)網(wǎng)站改版、網(wǎng)站營(yíng)銷(xiāo)、域名注冊(cè)面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)