定義
定義了算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化不會影響到使用算法的用戶。
if…else…
類型
行爲型
適用場景
①、系統有很多類,而它們的區別僅僅在於它們的行爲不同。
②、一個系統需要動態地在幾種算法中選擇一種。
優缺點
優點:
①、開閉原則
②、避免使用多重條件轉移語句
③、提高算法的保密性和安全性
缺點:
①、客戶端必須知道所有的策略類,並自行決定使用哪一個策略類
②、 產生很多策略類
代碼實現
案例:電商網站經常會在不同的節日搞不同的促銷活動,例如:滿減、立減、返現等等。根據這個場景來使用策略模式實現。
首先創建一個促銷策略的接口
public interface PromotionStrategy {
/**
* 促銷
*/
void doPromotion();
}
然後,分別創建不同促銷策略的實現類。
返現促銷
public class FanXianPromotionStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("返現促銷,返回的金額存放到用戶的餘額中");
}
}
立減促銷
public class LiJianPromotionStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("立減促銷,課程的價格直接減去配置的價格");
}
}
滿減促銷
public class ManJianPromotionStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("滿減促銷,滿100減50");
}
}
無促銷活動
public class EmptyPromotionStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("無促銷策略");
}
}
促銷策略有了,還需要創建具體的促銷活動
public class PromotionActivity {
private PromotionStrategy promotionStrategy;
public PromotionActivity(PromotionStrategy promotionStrategy) {
this.promotionStrategy = promotionStrategy;
}
public void execute() {
promotionStrategy.doPromotion();
}
}
創建測試類
public class MainTest {
public static void main(String[] args) {
PromotionActivity promotionActivity = null;
// 前臺傳過來的標誌
String PromotionKey = "LiJian";
if (StringUtils.equals(PromotionKey, "LiJian")) {
// 京東618立減
promotionActivity = new PromotionActivity(new LiJianPromotionStrategy());
} else if (StringUtils.equals(PromotionKey, "ManJian")) {
// 雙11 滿減
promotionActivity = new PromotionActivity(new ManJianPromotionStrategy());
} else {
promotionActivity = new PromotionActivity(new EmptyPromotionStrategy());
}
promotionActivity.execute();
}
}
輸出結果:
C:\android\java\jdk1.8\bin\java.exe
立減促銷,課程的價格直接減去配置的價格
基本上策略模式就實現了,但是查看上面的代碼,在開放立減策略或者其他策略的時候,都需要重新new一個當前的策略,這並不是我們所需要的。爲了消除if…else…以及避免多次重複的創建對象,結合工廠設計模式對當前的代碼進行改進。
首先創建一個策略工廠
public class PromotionStrategyFactory {
/**
* 存放所有促銷策略
*/
private static final Map<String, PromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<>();
/**
* 沒有促銷
*/
private static final EmptyPromotionStrategy EMPTY_PROMOTION_STRATEGY = new EmptyPromotionStrategy();
private interface PromotionKey {
String LIJian = "LiJian";
String FanXian = "FanXian";
String ManJian = "ManJian";
}
static {
PROMOTION_STRATEGY_MAP.put(PromotionKey.FanXian, new FanXianPromotionStrategy());
PROMOTION_STRATEGY_MAP.put(PromotionKey.LIJian, new LiJianPromotionStrategy());
PROMOTION_STRATEGY_MAP.put(PromotionKey.ManJian, new ManJianPromotionStrategy());
}
private PromotionStrategyFactory() {
}
public static PromotionStrategy getPromotionStrategy(String PromotionKey) {
PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(PromotionKey);
return promotionStrategy == null ? EMPTY_PROMOTION_STRATEGY : promotionStrategy;
}
}
這裏使用Map來存放所有的促銷策略,並在應用初始化時,就將策略放入Map集合中,並提供獲取策略的方法。
編寫測試類
@Test
public void testMethod2(){
// 前臺傳過來的標誌
String PromotionKey = "ManJian";
PromotionActivity promotionActivity = new PromotionActivity(PromotionStrategyFactory.getPromotionStrategy(PromotionKey));
promotionActivity.execute();
}
輸出結果:
C:\android\java\jdk1.8\bin\java.exe
滿減促銷,滿100減50
這樣就將if…else…消除了,並且簡化了代碼,使得代碼的業務邏輯變得優雅。
相關源碼
1. Jdk中的Comparator比較器。
2. Spring中的org.springframework.core.io.Resource。
3. Spring中bean初始化使用的InstantiationStrategy。