一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 對比Java設計模式編程中的狀態模式和策略模式

對比Java設計模式編程中的狀態模式和策略模式

2020-04-20 14:01花名有孚 JAVA教程

這篇文章主要介紹了Java設計模式編程中的狀態模式和策略模式對比,文中列舉了兩種模式的相似點和不同點,并都舉了代碼的實例作為參照,需要的朋友可以參考下

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

狀態模式和策略模式的相似點:
如果你看下策略模式和狀態模式的UML圖,它們看起來非常相似。在狀態模式中,使用State對象來改變行為的的對象叫Context對象,類似的在策略模式中,使用Strategy對象來改變行為的對象也是Context對象。記住,客戶端是和Context對象交互的。在狀態模式中,Context代理了狀態對象的方法調用,Context中的當前對象就是具體的狀態對象,而在策略模式中,Context操作的也是策略對象,這個對象要么作為參數傳入進來,要么是在創建Context對象的時候就已經提供了。

我們再來看一下這兩種核心的Java設計模式的一些相似點:

狀態模式和策略模式都很容易新增新的狀態或者策略,而不會影響到使用它們的Context對象
兩種模式都遵循開閉的設計原則,也就是說你的設計對擴展開放而對修改關閉。在這兩個模式里,Context對修改是封閉的,新增狀態或者策略,你不需要修改其它狀態的Context對象,或者只需要很小的改動
正如狀態模式中Context對象會有一個初始狀態一樣,策略模式中的Context通常也有一個默認的策略。
狀態模式以不同的狀態對象的方式來封裝不同的行為,而策略模式以不同的策略對象來封裝不同的行為。
這兩種模式都依賴具體的子類來實現具體的行為。每一個具體的策略都擴展自一個抽象的策略類,每個狀態也都是用來表示狀態的接口或者抽象類的子類。


狀態模式實例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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() {
    /*
     * 根據不同狀態做不同操作, 再切換狀態
     */
    if ("窗口".equals(stateValue)) {
      switchWindow();
      this.stateValue = "全屏";
    } else if ("全屏".equals(stateValue)) {
      switchFullscreen();
      this.stateValue = "窗口";
    }
  }
   
  private void switchWindow() {
    System.out.println("切換為窗口狀態");
  }
   
  private void switchFullscreen() {
    System.out.println("切換為全屏狀態");
  }
   
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
 * 狀態的使用
 */
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();
  }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * 狀態(State)模式 行為型模式
 * 既改變對象的狀態,又改變對象的行為
 * 根據狀態,改變行為
 */
public class Test {
  public static void main(String[] args) {
    /*
     * 本例的 狀態值只有兩個,由狀態類自身控制
     * 也可以把狀態值的控制,交由客戶端來設置
     */
    WindowContext context = new WindowContext(new WindowState("窗口"));
    context.switchState();
    context.switchState();
    context.switchState();
    context.switchState();
 
  }
}

打印

?
1
2
3
4
切換為窗口狀態
切換為全屏狀態
切換為窗口狀態
切換為全屏狀態


策略模式實例

?
1
2
3
4
5
6
7
/**
 * 商品促銷
 * 本類為:收取現金的類
 */
public interface ICashSuper {
   double acceptCash(double money);
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * 正常收取現金
 * @author stone
 *
 */
public class CashNormal implements ICashSuper {
 
  @Override
  public double acceptCash(double money) {
    return money;
  }
 
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 * 打折收取現金
 * @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();
  }
   
   
}

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * 讓利返現 收取現金
 * @author stone
 *
 */
public class CashReturn implements ICashSuper {
  private double moneyCondition; //返現底限金額
  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;
    }
  }
   
   
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * 根據傳遞的的策略類,執行相應的行為
 */
public class CashContext {
  private ICashSuper casher;
   
  public CashContext() {
     
  }
   
  public CashContext(ICashSuper casher) {
    this.casher = casher;
  }
   
  public void setCasher(ICashSuper casher) {
    this.casher = casher;
  }
   
  //根據具體的策略對象,調用它的算法行為
  public double acceptCash(double money) {
    return this.casher.acceptCash(money);
  }
   
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test {
  public static void main(String[] args) {
    double money = 998; //原價
    CashContext cashContext = new CashContext(new CashNormal());
    System.out.println("原價:" + 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("滿300 返50:" + cashContext.acceptCash(money)); //返現 策略  滿300 返50
     
  }
}

打印

?
1
2
3
原價:998.0
打85折:848.3
滿300 返50:848.0

策略模式和狀態模式的區別
我們已經了解到這兩個模式在結構上非常相似,但它們仍有不同的地方。下面來看下它們之間一些關鍵的不同點。

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

這就是關于Java中策略模式和狀態模式的所有區別。正如我所說的,它們在UML圖中看起來非常類似,兩者都遵循了開閉原則,并且封裝了行為。策略模式是用來封裝算法或者策略的,它會在運行時作為參數或者組合對象來提供給Context對象,而狀態模式則是用來管理狀態遷移 的。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲国产美女精品久久久久 | 免费波多野结衣庭教师 | 青青草国产精品免费 | 97国产蝌蚪视频在线观看 | 性色AV乱码一区二区三区视频 | 人人揉揉香蕉 | 青草热视频 | 色悠久久久久综合欧美99 | 亚洲精品第三页 | 久久精品国产在热亚洲 | 国产精品俺来也在线观看了 | 91精品国产亚一区二区三区 | 成人影院vs一区二区 | 亚洲图片 自拍偷拍 | 五月色综合婷婷综合俺来也 | 99视频久久精品久久 | 10个免费货源网站 | 性xxxx欧美高清 | 日日操天天射 | 亚洲aⅴ天堂 | 亚洲国产无线码在线观看 | 欧美性一区二区三区 | 日韩制服丝袜在线观看 | 超鹏97国语 | 特黄特色大片免费视频大全 | 调教催眠改造np总攻 | 91韩国女主播 | 亚洲国产精品无码中文字满 | 四虎在线视频免费观看视频 | 欧美在线观看一区二区三 | 日本公与妇中文在线 | sxx免费看视频在线播放 | 特色特色大片在线 | 国精视频一区二区视频 | 久久影院中文字幕 | 日韩欧美一区二区三区中文精品 | 秋霞理论最新三级理论最 | 久久久久久免费观看 | 成人伊人亚洲人综合网站222 | 女教师三级做受 | 毛片免费的 |