Java通俗易懂系列設(shè)計(jì)模式之策略模式
介紹
策略設(shè)計(jì)模式是行為設(shè)計(jì)模式之一。當(dāng)我們?yōu)樘囟ㄈ蝿?wù)使用多個(gè)算法時(shí),使用策略模式,客戶端決定在運(yùn)行時(shí)使用的實(shí)際實(shí)現(xiàn)。

策略模式的最佳示例之一是Collections.sort()采用Comparator參數(shù)的方法?;贑omparator接口的不同實(shí)現(xiàn),對(duì)象將以不同的方式進(jìn)行排序。
實(shí)例
對(duì)于我們的示例,我們將嘗試實(shí)施一個(gè)簡(jiǎn)單的購物車,我們有兩種付款策略 - 使用信用卡或使用PayPal。
首先,我們將為我們的策略模式示例創(chuàng)建接口,在我們的例子中,支付金額作為參數(shù)傳遞。
支付方式:PaymentStrategy.java
package com.journaldev.design.strategy;
public interface PaymentStrategy {
public void pay(int amount);
}
現(xiàn)在我們將不得不使用信用卡/借記卡或通過PayPal為支付創(chuàng)建具體的算法實(shí)現(xiàn)。
信用卡付款:CreditCardStrategy.java
package com.journaldev.design.strategy;
public class CreditCardStrategy implements PaymentStrategy {
private String name;
private String cardNumber;
private String cvv;
private String dateOfExpiry;
public CreditCardStrategy(String nm, String ccNum, String cvv, String expiryDate){
this.name=nm;
this.cardNumber=ccNum;
this.cvv=cvv;
this.dateOfExpiry=expiryDate;
}
@Override
public void pay(int amount) {
System.out.println(amount +" paid with credit/debit card");
}
}
Paypal付款:PaypalStrategy.java
package com.journaldev.design.strategy;
public class PaypalStrategy implements PaymentStrategy {
private String emailId;
private String password;
public PaypalStrategy(String email, String pwd){
this.emailId=email;
this.password=pwd;
}
@Override
public void pay(int amount) {
System.out.println(amount + " paid using Paypal.");
}
}
現(xiàn)在我們的策略模式示例算法準(zhǔn)備好了。我們可以實(shí)施購物車和付款方式將需要輸入作為付款策略。
package com.journaldev.design.strategy;
public class Item {
private String upcCode;
private int price;
public Item(String upc, int cost){
this.upcCode=upc;
this.price=cost;
}
public String getUpcCode() {
return upcCode;
}
public int getPrice() {
return price;
}
}
ShoppingCart.java
package com.journaldev.design.strategy;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
public class ShoppingCart {
//List of items
List<Item> items;
public ShoppingCart(){
this.items=new ArrayList<Item>();
}
public void addItem(Item item){
this.items.add(item);
}
public void removeItem(Item item){
this.items.remove(item);
}
public int calculateTotal(){
int sum = 0;
for(Item item : items){
sum += item.getPrice();
}
return sum;
}
public void pay(PaymentStrategy paymentMethod){
int amount = calculateTotal();
paymentMethod.pay(amount);
}
}
請(qǐng)注意,購物車的付款方式需要付款算法作為參數(shù),并且不會(huì)將其作為實(shí)例變量存儲(chǔ)在任何位置。
讓我們用一個(gè)簡(jiǎn)單的程序測(cè)試我們的策略模式示例設(shè)置。
ShoppingCartTest.java
package com.journaldev.design.strategy;
public class ShoppingCartTest {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
Item item1 = new Item("1234",10);
Item item2 = new Item("5678",40);
cart.addItem(item1);
cart.addItem(item2);
//pay by paypal
cart.pay(new PaypalStrategy("myemail@example.com", "mypwd"));
//pay by credit card
cart.pay(new CreditCardStrategy("Pankaj Kumar", "1234567890123456", "786", "12/15"));
}
}
上述程序的輸出是:
50 paid using Paypal.
50 paid with credit/debit card
類圖

總結(jié)
我們可以使用組合為策略創(chuàng)建實(shí)例變量,但我們應(yīng)該避免這種情況,因?yàn)槲覀兿M麑⑻囟ú呗詰?yīng)用于特定任務(wù)。在Collections.sort()和Arrays.sort()方法中遵循相同的方法,將比較器作為參數(shù)。
策略模式與狀態(tài)模式(State Pattern)非常相似。其中一個(gè)區(qū)別是Context包含狀態(tài)作為實(shí)例變量,并且可以有多個(gè)任務(wù),其實(shí)現(xiàn)可以依賴于狀態(tài),而策略模式策略作為參數(shù)傳遞給方法,上下文對(duì)象沒有任何變量來存儲(chǔ)它。
當(dāng)我們?yōu)樘囟ㄈ蝿?wù)提供多個(gè)算法時(shí),策略模式很有用,我們希望我們的應(yīng)用程序可以靈活地在運(yùn)行時(shí)為特定任務(wù)選擇任何算法。
- 優(yōu)點(diǎn):1、算法可以自由切換。2、避免使用多重條件判斷。3、擴(kuò)展性良好。
- 缺點(diǎn):1、策略類會(huì)增多。 2、所有策略類都需要對(duì)外暴露。
- 主要解決:在有多種算法相似的情況下,使用 if...else 所帶來的復(fù)雜和難以維護(hù)。
- 何時(shí)使用:一個(gè)系統(tǒng)有許多許多類,而區(qū)分它們的只是他們直接的行為。
- 如何解決:將這些算法封裝成一個(gè)一個(gè)的類,任意地替換。
- 關(guān)鍵代碼:實(shí)現(xiàn)同一個(gè)接口。
- 使用場(chǎng)景: 1、如果在一個(gè)系統(tǒng)里面有許多類,它們之間的區(qū)別僅在于它們的行為,那么使用策略模式可以動(dòng)態(tài)地讓一個(gè)對(duì)象在許多行為中選擇一種行為。 2、一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種。 3、如果一個(gè)對(duì)象有很多的行為,如果不用恰當(dāng)?shù)哪J?,這些行為就只好使用多重的條件選擇語句來實(shí)現(xiàn)。
- 注意事項(xiàng):如果一個(gè)系統(tǒng)的策略多于四個(gè),就需要考慮使用混合模式,解決策略類膨脹的問題。
以上就是Java通俗易懂系列設(shè)計(jì)模式之策略模式的詳細(xì)內(nèi)容,更多關(guān)于Java設(shè)計(jì)模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解Spring Cloud Zuul網(wǎng)關(guān)修改為短連接方法
本文主要介紹了詳解Spring Cloud Zuul網(wǎng)關(guān)修改為短連接方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04
使用Java實(shí)現(xiàn)KMZ和KML數(shù)據(jù)的直接解析
本文主要講解如何用JAVA語言,直接解析KMZ數(shù)據(jù),文章首先介紹google地圖中的KMZ和KML數(shù)據(jù),然后使用代碼的方式實(shí)現(xiàn)數(shù)據(jù)的解析,最后展示解析成果以及如何將數(shù)據(jù)轉(zhuǎn)換成空間WKT數(shù)據(jù),需要的朋友可以參考下2024-06-06
springboot簡(jiǎn)單集成Security配置的教程
這篇文章主要介紹了springboot簡(jiǎn)單集成Security配置的教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03
Java實(shí)現(xiàn)簡(jiǎn)單的分頁功能
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單的分頁功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
JVM中對(duì)象的創(chuàng)建與OOP-Klass模型
這篇文章主要介紹了JVM中對(duì)象的創(chuàng)建與OOP-Klass模型,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09

