自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

點(diǎn)外賣,讓我想起了 策略模式

開(kāi)發(fā) 前端
策略模式:英文為Strategy Pattern,是指定義了算法家族、分別封裝起來(lái),讓他們之間可以相互替換,此設(shè)計(jì)模式讓算法的變化不會(huì)影響到使用算法的用戶。

[[402404]]

今天給大家分享的是策略模式,具體內(nèi)容大綱如下:

生活案例

在這互聯(lián)網(wǎng)時(shí)代,尤其是在城市中,有一幫騎著電瓶車,穿梭在大街小巷中,這幫人就是外賣小哥。

[[402405]]

對(duì)于點(diǎn)外賣,我也點(diǎn)過(guò)不少。有一次,外賣下單的時(shí)候,我突然聯(lián)想到了一個(gè)設(shè)計(jì)模式---策略模式。

策略模式是個(gè)啥?

策略模式:英文為Strategy Pattern,是指定義了算法家族、分別封裝起來(lái),讓他們之間可以相互替換,此設(shè)計(jì)模式讓算法的變化不會(huì)影響到使用算法的用戶。

英文

Define a family of algorithms,encapsulate each one,and make them interchangeable.

大致意思:定義一組算法,將每個(gè)算法都封裝起來(lái),并且使它們之間可以互換。

在策略模式中,一個(gè)類的行為或其算法可以在運(yùn)行時(shí)更改。這種類型的設(shè)計(jì)模式屬于行為型模式。

策略模式通用代碼

java代碼實(shí)現(xiàn)如下:

  1. class Client { 
  2.  
  3.     //抽象策略類 Strategy 
  4.     interface IStrategy { 
  5.         void algorithm(); 
  6.     } 
  7.  
  8.     //具體策略類 ConcreteStrategy 
  9.     static class ConcreteStrategyA implements IStrategy { 
  10.  
  11.         @Override 
  12.         public void algorithm() { 
  13.             System.out.println("Strategy A"); 
  14.         } 
  15.     } 
  16.  
  17.     //具體策略類 ConcreteStrategy 
  18.     static class ConcreteStrategyB implements IStrategy { 
  19.  
  20.         @Override 
  21.         public void algorithm() { 
  22.             System.out.println("Strategy B"); 
  23.         } 
  24.     } 
  25.  
  26.     //上下文環(huán)境 
  27.     static class Context { 
  28.         private IStrategy mStrategy; 
  29.  
  30.         public Context(IStrategy strategy) { 
  31.             this.mStrategy = strategy; 
  32.         } 
  33.  
  34.         public void algorithm() { 
  35.             this.mStrategy.algorithm(); 
  36.         } 
  37.     } 
  38.      
  39.    public static void main(String[] args) { 
  40.         //選擇一個(gè)具體策略 
  41.         IStrategy strategy = new ConcreteStrategyA(); 
  42.         //來(lái)一個(gè)上下文環(huán)境 
  43.         Context context = new Context(strategy); 
  44.         //客戶端直接讓上下文環(huán)境執(zhí)行算法 
  45.         context.algorithm(); 
  46.     } 

從上面的通用代碼,我們可以得知其UML圖。

策略模式UML圖

策略模式中的角色

從 UML 類圖中,我們可以看到,策略模式主要包含三種角色:

  • 上下文角色(Context):用來(lái)操作策略的上下文環(huán)境,屏蔽高層模塊(客戶端)對(duì)策略,算法的直接訪問(wèn),封裝可能存在的變化;
  • 抽象策略角色(Strategy):規(guī)定策略或算法的行為;
  • 具體策略角色(ConcreteStrategy):具體的策略或算法實(shí)現(xiàn);

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

優(yōu)點(diǎn)

  • 策略模式符合開(kāi)閉原則
  • 避免使用多重轉(zhuǎn)換語(yǔ)句,比如:if...else、switch語(yǔ)句。
  • 使用策略模式可以提高算法的保密性和安全性

缺點(diǎn)

  • 客戶端必須知道所有策略,并且自行決定使用哪一種策略
  • 代碼中產(chǎn)生非常多的策略類,增加后期維護(hù)難度

策略模式使用場(chǎng)景

在日常開(kāi)發(fā)中,策略模式適用于以下三種場(chǎng)景:

  • 針對(duì)同一類型問(wèn)題,有多重處理方式,每一種都能獨(dú)立解決問(wèn)題。
  • 算法需要自由切換的場(chǎng)景。
  • 需要屏蔽算法規(guī)則的場(chǎng)景

這個(gè)說(shuō)起來(lái),還是不太好理解。

下面,我們就來(lái)使用生活案例來(lái)實(shí)現(xiàn),讓大家知道策略模式到底是怎么使用的。

支付案例代碼重構(gòu),三個(gè)版本

外面下單,選擇支付方式的時(shí)候,我覺(jué)這個(gè)功能,我們可以模仿著使用策略模式來(lái)實(shí)現(xiàn)一下。下面我們通過(guò)三個(gè)版本的迭代來(lái)實(shí)現(xiàn),很有意思的。

第一版

先定義一個(gè)抽象類Pay:

  1. //定義抽象類,我們可以把一些共用功能放在抽象類里實(shí)現(xiàn) 
  2. //比如:可用余額和本次支付金額進(jìn)行比較,統(tǒng)一返回“支付失敗” 
  3. public abstract class  Pay { 
  4.     abstract  void doPay(); 

下面模擬三種支付方式:

  1. public class AliPay extends Pay { 
  2.     @Override 
  3.     public void doPay() { 
  4.         System.out.println("使用支付寶支付"); 
  5.     } 
  6. public class UnionPay extends Pay { 
  7.     @Override 
  8.     public void doPay() { 
  9.         System.out.println("使用銀聯(lián)支付"); 
  10.     } 
  11. public class WechatPay extends Pay { 
  12.     @Override 
  13.     public void doPay() { 
  14.         System.out.println("使用微信支付"); 
  15.     } 

我們?cè)賮?lái)進(jìn)行支付:

  1. public class PayTest { 
  2.     public static void main(String[] args) { 
  3.         //把選擇權(quán)交給了用戶 
  4.         Order order = new Order(new WechatPay()); 
  5.         order.pay();* 
  6.     } 

運(yùn)行結(jié)果:

  1. 使用微信支付 

這樣我們就使用策略模式實(shí)現(xiàn)了簡(jiǎn)單版本的支付,但是其中有個(gè)很不爽的地方,就是每次還得自己手工new一個(gè)支付方式的對(duì)象。鑒于此,我們對(duì)第一版進(jìn)行重構(gòu)。

第二版

前面的實(shí)現(xiàn)都不變,變化的是發(fā)起支付的時(shí)候,只要前端傳一個(gè)key過(guò)來(lái)就可以了,實(shí)現(xiàn)如下:

  1. public class PayTest { 
  2.     public static void main(String[] args) {  
  3.  
  4.         String payKey = "Wechat"
  5.         Order order = null
  6.         //通過(guò)判斷前端傳過(guò)來(lái)的key,判斷使用哪種支付方式 
  7.         if (payKey.equals("Ali")) { 
  8.             order = new Order(new AliPay()); 
  9.         } else if (payKey.equals("Wechat")) { 
  10.             order = new Order(new WechatPay()); 
  11.         } else if (payKey.equals("union")) { 
  12.             order = new Order(new UnionPay()); 
  13.         }else { 
  14.             //給出一個(gè)默認(rèn)方式 
  15.             order = new Order(new WechatPay()); 
  16.         } 
  17.         order.pay(); 
  18.     } 

運(yùn)行結(jié)果

  1. 使用微信支付 

這樣我們就實(shí)現(xiàn)了,通過(guò)前端傳過(guò)來(lái)的key,然后選出對(duì)應(yīng)的支付方式。但是問(wèn)題又來(lái)了,如果支付方式不斷增多,那這里的if...else豈不是會(huì)越來(lái)越多嗎?后續(xù)維護(hù)成本不是越來(lái)越大嗎?

于是,第三版就有了。

第三版

在第二版中,會(huì)出現(xiàn)大量的if...else,會(huì)給后續(xù)的代碼維護(hù)帶來(lái)不便,于是在這一版中,我們對(duì)其進(jìn)行重構(gòu),引入了注冊(cè)式單例模式。

  1. import java.util.HashMap; 
  2. import java.util.Map; 
  3.  
  4. public enum PayStrategyEnum { 
  5.     ALI_PAY("Ali"), 
  6.     WECHAT_PAY("Wechat"), 
  7.     UNION_PAY("union"), 
  8.     //默認(rèn)使用微信支付 
  9.     DEFAULT_PAY("Wechat"); 
  10.  
  11.     private String key
  12.  
  13.     PayStrategyEnum(String key) { 
  14.         this.key = key
  15.     } 
  16.  
  17.     private static final Map<String, Pay> payKeyMap = new HashMap(); 
  18.  
  19.     static { 
  20.         payKeyMap.put(ALI_PAY.key, new AliPay()); 
  21.         payKeyMap.put(WECHAT_PAY.key, new WechatPay()); 
  22.         payKeyMap.put(UNION_PAY.key, new UnionPay()); 
  23.         payKeyMap.put(DEFAULT_PAY.key, new WechatPay()); 
  24.     } 
  25.  
  26.     public static Pay getPay(String payKey) { 
  27.         if (!payKeyMap.containsKey(payKey)) { 
  28.             return payKeyMap.get(DEFAULT_PAY.key); 
  29.         } 
  30.         return payKeyMap.get(payKey); 
  31.     } 

然后,在訂單支付的時(shí)候就變成了這樣了:

  1. public class PayTest { 
  2.     public static void main(String[] args) {  
  3.         String payKey = "Wechat";  
  4.         Order order = new Order(PayStrategyEnum.getPay(payKey)); 
  5.         order.pay(); 
  6.     } 

運(yùn)行結(jié)果

  1. 使用微信支付 

這樣,我們就成功的規(guī)避了大量的if...else了,爽歪歪!

其實(shí),上面三個(gè)版本的代碼,是不是覺(jué)得很爽,這就是設(shè)計(jì)模式的強(qiáng)大之處。

PS:關(guān)于上面的三個(gè)版本,其實(shí)我們還可以繼續(xù)完善,繼續(xù)重構(gòu),感興趣的你可以去試試如何繼續(xù)重構(gòu)。

總結(jié)

好了,今天的策略模式就到這里。其實(shí),設(shè)計(jì)模式在大多數(shù)情況下,是不會(huì)單獨(dú)存在的,都是使用多種設(shè)計(jì)模式混合起來(lái)使用的。

策略模式使用的就是面向?qū)ο蟮睦^承和多態(tài)機(jī)制,從而實(shí)現(xiàn)同一行為在不同場(chǎng)景下不同實(shí)現(xiàn)。

最好記的案例:

我們可以使用不同的交通工具去北京玩

坐飛機(jī)、坐高鐵、坐汽車、開(kāi)車、騎車。方式很多,你想選哪一條就選那一條。

最后用一句話來(lái)總結(jié)策略模式:

條條大路通羅馬

本文轉(zhuǎn)載自微信公眾號(hào)「Java后端技術(shù)全?!?,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系Java后端技術(shù)全棧公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: Java后端技術(shù)全棧
相關(guān)推薦

2022-04-29 21:37:34

漏洞網(wǎng)絡(luò)安全網(wǎng)絡(luò)攻擊

2020-07-20 07:48:53

單例模式

2024-12-09 09:40:00

策略模式Java

2013-11-26 16:09:34

Android設(shè)計(jì)模式

2021-03-08 10:27:42

CIO銷售策略IBM

2015-09-08 13:39:10

JavaScript設(shè)計(jì)模式

2021-06-09 08:53:34

設(shè)計(jì)模式策略模式工廠模式

2021-04-26 06:03:07

Reacterror前端

2011-07-20 14:04:42

.NET策略模式

2012-08-30 09:07:33

設(shè)計(jì)模式

2021-06-17 06:19:20

存儲(chǔ)SQL數(shù)據(jù)庫(kù)

2017-07-07 10:55:14

數(shù)據(jù)庫(kù)MongoDB設(shè)計(jì)模式

2012-12-19 14:58:28

2024-10-06 12:56:36

Golang策略設(shè)計(jì)模式

2024-01-29 12:22:07

設(shè)計(jì)模式策略模式

2014-12-29 10:39:16

JS

2023-06-26 07:10:51

2024-01-22 11:48:20

策略模式開(kāi)發(fā)

2016-11-27 20:43:26

云計(jì)算迭代
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)