java 策略模式 促销_设计模式之策略模式
0x01.定義與類型
定義:定義了算法家族,分別封裝起來,讓它們之間可以相互替換,此模式讓算法的變化不會影響到使用算法的用戶。
從一系列里抽象出不變的部分
策略模式是將可變的部分從程序中抽象分離成算法接口,在該接口下分別封裝一系列算法實現(xiàn),并使他們可以相互替換,從而導致客戶端程序獨立于算法的改變。
類型:行為型
0x02.適用場景
系統(tǒng)有很多類,而他們的區(qū)別僅僅在于他們的行為不同
一個系統(tǒng)需要動態(tài)地在幾中算法中選擇一種
通過條件語句在多個分支中選取一
0x03.優(yōu)缺點
1.優(yōu)點
開閉原則
避免使用多重條件轉(zhuǎn)移語句
提高算法的保密性和安全性
2.缺點
客戶端必須知道所以的策略類,并自行決定使用哪一個策略類
產(chǎn)生很多的策略類
0x04.相關的設計模式
策略模式和工廠模式:工廠是創(chuàng)建對象,而策略是具體實現(xiàn)。
策略模式和狀態(tài)模式:使用策略,客戶端是不關心具體狀態(tài)的。
0x05.策略模式如何實現(xiàn)
1.繼承-在父類中提供實現(xiàn)方法,子類通過繼承獲得父類中的行為
優(yōu)點:簡單易用,已有的類可以快速添加父類的方法
缺點:不具有靈活性,對未來的變更支持差,需要覆寫子類的方法來提供新的行為
2.抽象方法-在父類中提供抽象方法,強迫子類實現(xiàn)自己的行為
優(yōu)點:足夠靈活。
缺點:每個子類都要實現(xiàn)一遍代碼,即使相同的行為也不例外,代碼重復,沒有復用的代碼。
3.組合-策略模式核心
解釋:在類中增加一個私有域,引用另一個已有的類的實例,通過調(diào)用引用實例的方法從而獲得新的功能,這種設計稱作組合(復合)。
將行為抽象為接口,在父類中持有該接口,并由該接口代替接口飛行行為
優(yōu)點:
足夠靈活,復用代碼,更易于維護
使用了組合,使架構更加靈活
富有彈性,可以較好的應對變化(開--閉原則)
正好的代碼復用型(相對于繼承)
消除大量的條件語句
缺點:
客戶代碼需要了解每個策略實現(xiàn)的細節(jié)
增加了對象的數(shù)目(維護困難)
4.注意
繼承是重用代碼的利器,但繼承并不是最好的工具。
Favor composition over inheritance.(復合優(yōu)于繼承)
0x06.策略模式的實現(xiàn)
通過分離變化得出的策略接口Strategy
Strategy的實現(xiàn)類
客戶程序中有一個Strategy
在客戶程序中選擇/組裝正確的Strategy實現(xiàn)
1.使用策略模式實現(xiàn)超市促銷
需求
原價返回
打折
滿減~~~~
策略類(IPromotionStrategy)定義
/**
* 促銷策略類
*/
public interface IPromotionStrategy {
/**
* 計算邏輯
*/
BigDecimal promotionAlgorithm();
/**
* 存入價錢
* @param price
*/
void setPrice(BigDecimal price);
}
根據(jù)不同情況實現(xiàn)策略類
/**
* 原價
*/
public class CashNormal implements IPromotionStrategy{
private BigDecimal price;
@Override
public BigDecimal promotionAlgorithm() {
//原價返回
return this.price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
}
/**
* 打折
*/
public class CashRebate implements IPromotionStrategy {
private BigDecimal price = BigDecimal.ZERO;
private BigDecimal rate;
public CashRebate(BigDecimal rate) {
this.rate = rate;
}
@Override
public BigDecimal promotionAlgorithm() {
//TODO 打折邏輯實現(xiàn)
}
public void setPrice(BigDecimal price) {
this.price = price;
}
}
/**
* 滿減
*/
public class CashReturn implements IPromotionStrategy {
private BigDecimal price;
private BigDecimal minPrice;
private BigDecimal subPrice;
public CashReturn(BigDecimal minPrice, BigDecimal subPrice) {
this.minPrice = minPrice;
this.subPrice = subPrice;
}
@Override
public BigDecimal promotionAlgorithm() {
//TODO 滿減邏輯實現(xiàn)
}
public void setPrice(BigDecimal price) {
this.price = price;
}
}
創(chuàng)建打折上下文(PromotionContext), 維護使用促銷模式
public class PromotionContext {
/**
* 策略實現(xiàn)類包
*/
private static final String PACKAGE_NAME = "org.ko.strategy.promotion";
/**
* 組合策略類
*/
private IPromotionStrategy promotionStrategy;
/**
* 獲取促銷后價錢
* @return
*/
public BigDecimal getPrice () {
return this.promotionStrategy.promotionAlgorithm();
}
/**
* 創(chuàng)建促銷手段
* 這里使用反射維護實例對象, 相關知識這里不再介紹.
* @param code 對應促銷模式編碼
* @param args 對應促銷參數(shù)
*/
public void newPromotion (Integer code, Object... args) {
//根據(jù)促銷模式編碼獲取促銷模式對應類名稱
String clazz = PromotionType.findClazz(code);
try {
//通過反射獲取促銷模式的對象
this.promotionStrategy = (IPromotionStrategy)Class.forName(PACKAGE_NAME + "." + clazz)
.getDeclaredConstructor(getClasses(args)).newInstance(args);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 設置打折前的價格
* @param price
*/
public void setPrice (BigDecimal price) {
this.promotionStrategy.setPrice(price);
}
/**
* 獲取Class
* @param args
* @return
*/
private Class[] getClasses (Object... args) {
Class[] classes = new Class[args.length];
for (int i = 0; i < args.length; i ++) {
classes[i] = args[i].getClass();
}
return classes;
}
}
創(chuàng)建枚舉維護促銷樣例
/**
* 促銷手段樣例
*/
public enum PromotionType {
CashNormal(1, "CashNormal", "原價"),
CashRebate(2, "CashRebate", "打折"),
CashReturn(3, "CashReturn", "滿減");
private Integer code;
private String clazz;
private String description;
PromotionType(Integer code, String clazz, String description) {
this.code = code;
this.clazz = clazz;
this.description = description;
}
/**
* 通過編碼獲取促銷手段
* @param code 促銷手段編碼
* @return
*/
public static String findClazz(Integer code) {
for (PromotionType type : PromotionType.values()) {
if (Objects.equals(code, type.code)) {
return type.clazz;
}
}
return null;
}
}
測試與應用
public static void main(String[] args) {
//初始化上下文
PromotionContext context = new PromotionContext();
//測試無促銷
context.newPromotion(1);
context.setPrice(new BigDecimal("200"));
BigDecimal price = context.getPrice();
System.out.println(price);
//測試打折
context.newPromotion(2, new BigDecimal("0.8"));
context.setPrice(new BigDecimal("200"));
price = context.getPrice();
System.out.println(price);
//測試滿減
context.newPromotion(3, new BigDecimal("300"), new BigDecimal("100"));
context.setPrice(new BigDecimal("200"));
price = context.getPrice();
System.out.println(price);
context.setPrice(new BigDecimal("300"));
price = context.getPrice();
System.out.println(price);
}
策略模式總結(jié)篇
將一些方法抽象成接口
在基類中實例化接口
設置接口的私有成員變量
在積累中調(diào)用接口的同樣方法
這樣實現(xiàn)了代碼的復用
面向接口編程,而不是面向?qū)崿F(xiàn)編程,多用組合
適用場景
許多相關的類僅僅是行為差異
運行時選取不同的算法遍體
通過條件語句在多個分支中選取一
0x07.源碼中的策略模式
Comparator, Arrays
TreeMap
Resource
0x08.代碼地址
0x09.推薦
總結(jié)
以上是生活随笔為你收集整理的java 策略模式 促销_设计模式之策略模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。