最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

對(duì)比Java設(shè)計(jì)模式編程中的狀態(tài)模式和策略模式

 更新時(shí)間:2016年04月27日 11:54:45   作者:花名有孚  
這篇文章主要介紹了Java設(shè)計(jì)模式編程中的狀態(tài)模式和策略模式對(duì)比,文中列舉了兩種模式的相似點(diǎn)和不同點(diǎn),并都舉了代碼的實(shí)例作為參照,需要的朋友可以參考下

為了能在Java應(yīng)用程序中正確的使用狀態(tài)模式和策略模式,開(kāi)發(fā)人員需要清楚地知道這兩種模式之間的區(qū)別。盡管狀態(tài)模式和策略模式的結(jié)構(gòu)非常相似,它們又同樣遵循開(kāi)閉原則,都代表著SOLID設(shè)計(jì)原則的'O',但它們的意圖是完全不同的。Java中的策略模式是對(duì)一組相關(guān)的算法進(jìn)行封裝,給調(diào)用方提供了運(yùn)行時(shí)的靈活性。調(diào)用方可以在運(yùn)行時(shí)選擇不同的算法,而不用修改使用策略的那個(gè)Context類(lèi)。使用策略模式的經(jīng)典例子包括實(shí)現(xiàn)加密算法,壓縮算法,以及排序算法。另一方面,狀態(tài)模式使用一個(gè)對(duì)象可以在不同的狀態(tài)下表現(xiàn)出不同的行為。真實(shí)世界里的對(duì)象也是有狀態(tài)的,并且它們會(huì)隨著狀態(tài)的不同而有不同的表現(xiàn),比方說(shuō)自動(dòng)售貨機(jī),它只會(huì)在hasCoin狀態(tài)下才能出售物品,如果你不塞硬幣進(jìn)去它是不會(huì)售貨的?,F(xiàn)在你可以很清楚地看到策略模式和狀態(tài)模式的區(qū)別了,它們的目的是不一樣的。狀態(tài)模式可以幫助對(duì)象來(lái)管理它的狀態(tài),而策略模式使得客戶(hù)端可以選擇不同的行為。還有一個(gè)不太容易看到的區(qū)別是,誰(shuí)去驅(qū)動(dòng)行為的改變。在策略模式中,是客戶(hù)端驅(qū)動(dòng)的,它給上下文信息提供了不同的策略,而在狀態(tài)模式中,狀態(tài)的遷移是由Context或者State對(duì)象自己來(lái)管理的。同樣的,如果你在State對(duì)象里面進(jìn)行狀態(tài)的修改,它必須持有Context的引用,也就是說(shuō)對(duì)自動(dòng)售貨機(jī)而言,它可以調(diào)用setState方法來(lái)修改當(dāng)前Context的狀態(tài)。另一方面,策略對(duì)象不會(huì)持有Context的引用 ,它的客戶(hù)端將選中的策略傳遞給Context。策略模式和狀態(tài)模式是最容易碰見(jiàn)的關(guān)于Java設(shè)計(jì)模式的面試題,在這篇關(guān)于Java設(shè)計(jì)模式的文章里,我們將會(huì)對(duì)這點(diǎn)進(jìn)行詳細(xì)的介紹。我們會(huì)探索這兩種模式的相同點(diǎn)與不同點(diǎn),這有助于提高你對(duì)這兩種模式的理解。

狀態(tài)模式和策略模式的相似點(diǎn):
如果你看下策略模式和狀態(tài)模式的UML圖,它們看起來(lái)非常相似。在狀態(tài)模式中,使用State對(duì)象來(lái)改變行為的的對(duì)象叫Context對(duì)象,類(lèi)似的在策略模式中,使用Strategy對(duì)象來(lái)改變行為的對(duì)象也是Context對(duì)象。記住,客戶(hù)端是和Context對(duì)象交互的。在狀態(tài)模式中,Context代理了狀態(tài)對(duì)象的方法調(diào)用,Context中的當(dāng)前對(duì)象就是具體的狀態(tài)對(duì)象,而在策略模式中,Context操作的也是策略對(duì)象,這個(gè)對(duì)象要么作為參數(shù)傳入進(jìn)來(lái),要么是在創(chuàng)建Context對(duì)象的時(shí)候就已經(jīng)提供了。

我們?cè)賮?lái)看一下這兩種核心的Java設(shè)計(jì)模式的一些相似點(diǎn):

狀態(tài)模式和策略模式都很容易新增新的狀態(tài)或者策略,而不會(huì)影響到使用它們的Context對(duì)象
兩種模式都遵循開(kāi)閉的設(shè)計(jì)原則,也就是說(shuō)你的設(shè)計(jì)對(duì)擴(kuò)展開(kāi)放而對(duì)修改關(guān)閉。在這兩個(gè)模式里,Context對(duì)修改是封閉的,新增狀態(tài)或者策略,你不需要修改其它狀態(tài)的Context對(duì)象,或者只需要很小的改動(dòng)
正如狀態(tài)模式中Context對(duì)象會(huì)有一個(gè)初始狀態(tài)一樣,策略模式中的Context通常也有一個(gè)默認(rèn)的策略。
狀態(tài)模式以不同的狀態(tài)對(duì)象的方式來(lái)封裝不同的行為,而策略模式以不同的策略對(duì)象來(lái)封裝不同的行為。
這兩種模式都依賴(lài)具體的子類(lèi)來(lái)實(shí)現(xiàn)具體的行為。每一個(gè)具體的策略都擴(kuò)展自一個(gè)抽象的策略類(lèi),每個(gè)狀態(tài)也都是用來(lái)表示狀態(tài)的接口或者抽象類(lèi)的子類(lèi)。


狀態(tài)模式實(shí)例

public class WindowState { 
  private String stateValue; 
   
  public WindowState(String stateValue) { 
    this.stateValue = stateValue; 
  } 
   
  public String getStateValue() { 
    return stateValue; 
  } 
 
  public void setStateValue(String stateValue) { 
    this.stateValue = stateValue; 
  } 
   
  public void handle() { 
    /* 
     * 根據(jù)不同狀態(tài)做不同操作, 再切換狀態(tài) 
     */ 
    if ("窗口".equals(stateValue)) { 
      switchWindow(); 
      this.stateValue = "全屏"; 
    } else if ("全屏".equals(stateValue)) { 
      switchFullscreen(); 
      this.stateValue = "窗口"; 
    } 
  } 
   
  private void switchWindow() { 
    System.out.println("切換為窗口狀態(tài)"); 
  } 
   
  private void switchFullscreen() { 
    System.out.println("切換為全屏狀態(tài)"); 
  } 
   
} 
/** 
 * 狀態(tài)的使用 
 */ 
public class WindowContext { 
  private WindowState state; 
   
  public WindowContext(WindowState state) { 
    this.state = state; 
  } 
   
  public WindowState getState() { 
    return state; 
  } 
   
  public void setState(WindowState state) { 
    this.state = state; 
  } 
   
  public void switchState() { 
    this.state.handle(); 
  } 
} 

/* 
 * 狀態(tài)(State)模式 行為型模式 
 * 既改變對(duì)象的狀態(tài),又改變對(duì)象的行為 
 * 根據(jù)狀態(tài),改變行為 
 */ 
public class Test { 
  public static void main(String[] args) { 
    /* 
     * 本例的 狀態(tài)值只有兩個(gè),由狀態(tài)類(lèi)自身控制 
     * 也可以把狀態(tài)值的控制,交由客戶(hù)端來(lái)設(shè)置 
     */ 
    WindowContext context = new WindowContext(new WindowState("窗口")); 
    context.switchState(); 
    context.switchState(); 
    context.switchState(); 
    context.switchState(); 
 
  } 
} 

打印

切換為窗口狀態(tài) 
切換為全屏狀態(tài) 
切換為窗口狀態(tài) 
切換為全屏狀態(tài) 


策略模式實(shí)例

/** 
 * 商品促銷(xiāo) 
 * 本類(lèi)為:收取現(xiàn)金的類(lèi) 
 */ 
public interface ICashSuper { 
   double acceptCash(double money); 
} 
/** 
 * 正常收取現(xiàn)金 
 * @author stone 
 * 
 */ 
public class CashNormal implements ICashSuper { 
 
  @Override 
  public double acceptCash(double money) { 
    return money; 
  } 
 
} 

/** 
 * 打折收取現(xiàn)金 
 * @author stone 
 * 
 */ 
public class CashRebate implements ICashSuper { 
  private double rebate; //折扣 
  public CashRebate (double rebate) { 
    this.rebate = rebate; 
  } 
 
  @Override 
  public double acceptCash(double money) { 
    return new BigDecimal(money * rebate / 10).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); 
  } 
   
   
} 


/** 
 * 讓利返現(xiàn) 收取現(xiàn)金 
 * @author stone 
 * 
 */ 
public class CashReturn implements ICashSuper { 
  private double moneyCondition; //返現(xiàn)底限金額 
  private double returnMoney; //返還金額 
  public CashReturn(double moneyCondition, double returnMoney) { 
    this.moneyCondition = moneyCondition; 
    this.returnMoney = returnMoney; 
  } 
 
  @Override 
  public double acceptCash(double money) {//多重返利 
    if (money >= moneyCondition) { 
      return money - Math.floor(money / moneyCondition) * returnMoney; 
    } else { 
      return money; 
    } 
  } 
   
   
} 

/** 
 * 根據(jù)傳遞的的策略類(lèi),執(zhí)行相應(yīng)的行為 
 */ 
public class CashContext { 
  private ICashSuper casher; 
   
  public CashContext() { 
     
  } 
   
  public CashContext(ICashSuper casher) { 
    this.casher = casher; 
  } 
   
  public void setCasher(ICashSuper casher) { 
    this.casher = casher; 
  } 
   
  //根據(jù)具體的策略對(duì)象,調(diào)用它的算法行為 
  public double acceptCash(double money) { 
    return this.casher.acceptCash(money); 
  } 
   
} 

public class Test { 
  public static void main(String[] args) { 
    double money = 998; //原價(jià) 
    CashContext cashContext = new CashContext(new CashNormal()); 
    System.out.println("原價(jià):" + cashContext.acceptCash(money)); //通常 策略 
     
    cashContext.setCasher(new CashRebate(8.5)); 
    System.out.println("打85折:" + cashContext.acceptCash(money)); //折扣  策略  85折 
     
    cashContext.setCasher(new CashReturn(300, 50)); 
    System.out.println("滿(mǎn)300 返50:" + cashContext.acceptCash(money)); //返現(xiàn) 策略  滿(mǎn)300 返50 
     
  } 
} 

打印

原價(jià):998.0 
打85折:848.3 
滿(mǎn)300 返50:848.0 

策略模式和狀態(tài)模式的區(qū)別
我們已經(jīng)了解到這兩個(gè)模式在結(jié)構(gòu)上非常相似,但它們?nèi)杂胁煌牡胤?。下面?lái)看下它們之間一些關(guān)鍵的不同點(diǎn)。

  • 策略模式封裝了一系列的相關(guān)的算法,使用客戶(hù)端可以在運(yùn)行時(shí)通過(guò)組合和委托來(lái)使用不同的行為,而狀態(tài)模式使得對(duì)象可以在不同的狀態(tài)下展現(xiàn)出不同的行為。
  • 這兩個(gè)模式的另一個(gè)不同之處在于狀態(tài)模式封裝的是對(duì)象的狀態(tài),而策略模式封裝的是一個(gè)算法或者策略。由于狀態(tài)是和對(duì)象耦合在一起的,它無(wú)法重用,而通過(guò)策略或者算法獨(dú)立于它的上下文,使得它們可以重復(fù)使用。
  • 狀態(tài)模式中,狀態(tài)本身會(huì)包含Context的引用,從而實(shí)現(xiàn)狀態(tài)遷移 ,但策略模式則沒(méi)有Context的引用
  • 具體的策略可以作為一個(gè)參數(shù)傳遞給使用它們的對(duì)象,比如說(shuō)Collections.sort()接受一個(gè)Comparator,這是一個(gè)策略。另狀態(tài)本身 是 Context對(duì)象的一部分,隨著時(shí)間的遷移,Context對(duì)象會(huì)從一個(gè)狀態(tài)遷移遷移到另一個(gè)狀態(tài)下。
  • 盡管兩種模式都遵循了開(kāi)閉原則,策略模式還遵循了單一職責(zé)原則,因?yàn)槊總€(gè)策略都 封裝的是獨(dú)立 的算法,不同的策略獨(dú)立于其它策略。改變一個(gè)策略并不會(huì)影響到另一個(gè)策略的實(shí)現(xiàn)。
  • 從理論上說(shuō),策略模式和狀態(tài)模式還有一個(gè)不同,前者定義的是一個(gè)對(duì)象“如何”去做一件事情,比如說(shuō)如何對(duì)數(shù)據(jù)進(jìn)行排序,而另一方面,狀態(tài)模式定義的是“什么”以及“何時(shí)“,比如說(shuō)一個(gè)對(duì)象能做什么,某個(gè)時(shí)間點(diǎn)它處于哪個(gè)狀態(tài)。
  • 狀態(tài)的遷移順序在狀態(tài)模式中是定義好的,而策略模式則沒(méi)有這樣的要求。客戶(hù)端可以隨便選擇使用哪個(gè)策略。
  • 常見(jiàn)的策略模式的例子都是封裝算法,比如說(shuō)排序算法,加密算法,或者壓縮算法。如果你發(fā)現(xiàn)代碼中需要使用到不同的算法,那么你可以考慮使用策略模式。而如果你需要管理狀態(tài)進(jìn)行狀態(tài)間的遷移,而不希望嵌套許多條件語(yǔ)句,那么狀態(tài)模式就是你的首選,因?yàn)樗浅:?jiǎn)單.
  • 最后也是最重要的一個(gè)區(qū)別在于,策略模式是由客戶(hù)端進(jìn)行處理的,而狀態(tài)的改變Context或者State對(duì)象都可以進(jìn)行。

這就是關(guān)于Java中策略模式和狀態(tài)模式的所有區(qū)別。正如我所說(shuō)的,它們?cè)赨ML圖中看起來(lái)非常類(lèi)似,兩者都遵循了開(kāi)閉原則,并且封裝了行為。策略模式是用來(lái)封裝算法或者策略的,它會(huì)在運(yùn)行時(shí)作為參數(shù)或者組合對(duì)象來(lái)提供給Context對(duì)象,而狀態(tài)模式則是用來(lái)管理狀態(tài)遷移 的。

相關(guān)文章

  • Java利用位運(yùn)算實(shí)現(xiàn)乘法運(yùn)算詳解

    Java利用位運(yùn)算實(shí)現(xiàn)乘法運(yùn)算詳解

    這篇文章主要為大家詳細(xì)介紹了Java如何用位運(yùn)算實(shí)現(xiàn)乘法運(yùn)算,在實(shí)現(xiàn)乘法時(shí)要用位運(yùn)算實(shí)現(xiàn),并且不能出現(xiàn)加減乘除任何符號(hào),感興趣的可以了解一下
    2023-04-04
  • Java責(zé)任鏈模式模板代碼分享

    Java責(zé)任鏈模式模板代碼分享

    這篇文章主要介紹了Java責(zé)任鏈模式模板代碼分享,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • SpringBoot+ShardingSphereJDBC實(shí)現(xiàn)讀寫(xiě)分離詳情

    SpringBoot+ShardingSphereJDBC實(shí)現(xiàn)讀寫(xiě)分離詳情

    這篇文章主要介紹了SpringBoot+ShardingSphereJDBC實(shí)現(xiàn)讀寫(xiě)分離詳情,通過(guò)用??MySQL??進(jìn)行一主一從的主從復(fù)制展開(kāi)全文內(nèi)容,需要的朋友可以參考一下
    2022-08-08
  • Java基礎(chǔ)之Web服務(wù)器與Http詳解

    Java基礎(chǔ)之Web服務(wù)器與Http詳解

    無(wú)論你是前端開(kāi)發(fā)者還是后端開(kāi)發(fā)者,以及測(cè)試工程師,這篇文章的知識(shí)都是你需要弄懂的。讀完這一篇文章,將全面弄懂 HTTP 協(xié)議、TCP 協(xié)議,面試官再也難不倒你相關(guān)知識(shí)
    2021-09-09
  • Java中調(diào)用第三方接口的幾種方法詳細(xì)指南

    Java中調(diào)用第三方接口的幾種方法詳細(xì)指南

    在Java開(kāi)發(fā)中調(diào)用第三方接口是常見(jiàn)需求,本文介紹如何使用Java進(jìn)行接口調(diào)用,重點(diǎn)講解HttpURLConnection類(lèi)、OkHttp庫(kù)和ApacheHttpClient的使用,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-10-10
  • springcloud?feign服務(wù)之間調(diào)用,date類(lèi)型轉(zhuǎn)換錯(cuò)誤的問(wèn)題

    springcloud?feign服務(wù)之間調(diào)用,date類(lèi)型轉(zhuǎn)換錯(cuò)誤的問(wèn)題

    這篇文章主要介紹了springcloud?feign服務(wù)之間調(diào)用,date類(lèi)型轉(zhuǎn)換錯(cuò)誤的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java中static變量能繼承嗎

    Java中static變量能繼承嗎

    這篇文章主要介紹了Java中static變量能繼承,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • swagger中如何給請(qǐng)求添加header

    swagger中如何給請(qǐng)求添加header

    這篇文章主要介紹了swagger中如何給請(qǐng)求添加header,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • SpringBoot API接口超時(shí)時(shí)間的五種配置方式詳解

    SpringBoot API接口超時(shí)時(shí)間的五種配置方式詳解

    在開(kāi)發(fā)API接口時(shí),配置API接口的超時(shí)時(shí)間是一項(xiàng)非常重要的任務(wù),SpringBoot中有多種方式可以配置API接口的超時(shí)時(shí)間,下面小編就為大家介紹一下吧
    2025-03-03
  • Mybatis中Collection集合標(biāo)簽的使用詳解

    Mybatis中Collection集合標(biāo)簽的使用詳解

    這篇文章主要介紹了Mybatis中Collection集合標(biāo)簽的使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06

最新評(píng)論

合山市| 海兴县| 喀喇| 蕲春县| 新竹市| 延庆县| 辽宁省| 南充市| 怀化市| 来凤县| 静安区| 通州区| 普宁市| 南康市| 滦平县| 博罗县| 开江县| 虎林市| 冕宁县| 岱山县| 葫芦岛市| 九江市| 汾西县| 蒲城县| 象山县| 黎城县| 尉氏县| 镇坪县| 金山区| 昌邑市| 五台县| 沂南县| 长宁县| 合阳县| 云林县| 吉安市| 太保市| 无极县| 阳高县| 乌审旗| 邢台市|