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