Java設計模式學習記錄-策略模式
策略模式
策略模式的定義是:定義了一系列的算法,把它們一個個的封裝起來,并且使它們可相互替換,讓算法可以獨立于使用它的客戶而變化。
設計原則是:把一個類中經常改變或者將來可能會經常改變的部分提取出來作為一個接口,然后在使用類中包含這個接口的實例,這樣使用類的對象就可以隨意調用實現了這個接口的類行為。
在策略模式中有如下幾個角色:
環境角色(Context): 此角色中實現了對策略角色的引用和使用。
抽象策略角色:此角色通常由抽象類或接口來實現,定義了,所以具體策略角色的行為。
具體策略角色:此角色封裝了實現不同功能的不同算法。
演示代碼如下:
抽象策略類
public interface Strategy { /** * 策略方法 */ void strategyMethod(); }
具體角色類A
public class ConcreteStrategyA implements Strategy{ @Override public void strategyMethod() { //具體的行為 } }
具體角色類B
public class ConcreteStrategyB implements Strategy { @Override public void strategyMethod() { //具體的行為 } }
環境角色類
public class Context { /** * 持有一個具體的策略對象 */ private Strategy strategy; /** * 構造方法,傳入一個具體的策略對象 * @param strategy 具體的策略對象 */ public Context(Strategy strategy) { this.strategy = strategy; } /** * 對外提供的使用策略的方法 */ public void contextMethod() { //通常會轉調具體的策略對象進行算法運算 strategy.strategyMethod(); } }
策略模式具體場景例子
某Saas公司的企業服務系統,在銷售時,會根據客戶的購買時長來確定優惠策略,分為普通客戶(無優惠政策),大客戶(98折),戰略客戶(95折)。普通客戶是指一次性租用服務在一到3年之間的,大客戶指一次性使用服務3到5年之間的,戰略客戶指一次性使用服務5年以上的。因為每種客戶價格算法不同,所以這個場景就可以使用策略模式。
定義一個計算價格行為的接口
public interface SalePrice { /** * 根據原價返回不同的價格 * @param originalPrice 原始價格 * @return */ BigDecimal salePrice(BigDecimal originalPrice); }
然后定義三中客戶的具體計算價格類(策略類)
public class OriginalCustomer implements SalePrice { /** * 普通客戶直接返回原價 * @param originalPrice 原始價格 * @return 計算后的價格 */ @Override public BigDecimal salePrice(BigDecimal originalPrice) { return originalPrice.multiply(BigDecimal.valueOf(1)); } }
public class LargeCustomer implements SalePrice { /** * 大客戶返回98折價格 * @param originalPrice 原始價格 * @return 計算后的價格 */ @Override public BigDecimal salePrice(BigDecimal originalPrice) { return originalPrice.multiply(BigDecimal.valueOf(0.98)); } }
public class StrategicCustomer implements SalePrice { /** * 戰略客戶直接返回95折價格 * @param originalPrice 原始價格 * @return 計算后的價格 */ @Override public BigDecimal salePrice(BigDecimal originalPrice) { return originalPrice.multiply(BigDecimal.valueOf(0.95)); } }
客戶類,需要判斷具體的調用哪個計算價格的方法
public class Customer { private int years; /** 租用服務一年的初始價格 */ private BigDecimal originalPrice = BigDecimal.valueOf(50000); /** 客戶最終支付的價格 **/ private BigDecimal payForPrice = BigDecimal.ZERO; /** 每個客戶的初始價格都是原價 */ private SalePrice salePrice = new OriginalCustomer(); /** * 根據客戶購買的時長來計算每一年的優惠價格(單位:年) * @param years */ public void buy(int years) { this.years = years; payForPrice = originalPrice.multiply(BigDecimal.valueOf(years)); //大于5年的戰略客戶價格 if(years >= 5){ salePrice = new StrategicCustomer(); }else if(years >= 3)//3年到5年的大客戶優惠價格 { salePrice = new LargeCustomer(); }else if(years >= 1)//1到3年的普通用戶原價 { salePrice = new OriginalCustomer(); } } /** * 計算客戶最終支付的價格 * @return */ public BigDecimal payPrice(){ return salePrice.salePrice(payForPrice); } }
客戶端調用類,自動計算支付價格
** * 客戶端調用類 */ @Slf4j public class Client { public static void main(String[] args){ Customer customer = new Customer(); customer.buy(1); log.info("客戶需支付:{}",customer.payPrice()); customer.buy(3); log.info("客戶需支付:{}",customer.payPrice()); customer.buy(6); log.info("客戶需支付:{}",customer.payPrice()); } }
輸出結果:
客戶需支付:50000 客戶需支付:147000.00 客戶需支付:285000.00
根據輸出結果可以看出購買不同時間的服務,收費價格是不同的。這樣客戶可以不用依賴具體的收費方法,直接根據需要的服務的時間購買即可。
作者:紀莫
歡迎任何形式的轉載,但請務必注明出處。
限于本人水平,如果文章和代碼有表述不當之處,還請不吝賜教。
歡迎掃描二維碼關注公眾號:Jimoer
文章會同步到公眾號上面,大家一起成長,共同提升技術能力。
聲援博主:如果您覺得文章對您有幫助,可以點擊文章右下角【推薦】一下。
您的鼓勵是博主的最大動力!


浙公網安備 33010602011771號