設計模式學習筆記(三)——策略模式
一、概述
策略模式屬於對象的行為模式。其用意是針對一組算法,將每一個算法封裝到具有共同接口的獨立的類中,從而使得它們之間可以互相替換。策略模式使得算法可以在不影響客戶端的情況下發生變化。
策略模式是對算法的封裝,把一系列的算法分別封裝到對應的類中,並且這些類實現相同的接口,相互之間可以互相替換。在策略模式中,調用算法的主體是封裝到了封裝類Context中,抽象策略Strategy一般是一個接口,目的只是為了定義規範,裏面一般不包含邏輯。其實,這只是通用實現,而在實際編程中,因為各個具體策略實現類之間難免存在一些相同的邏輯,為了避免重復的代碼,我們常常使用抽象類來擔任Strategy的角色,在裏面封裝公共的代碼。
二、實現策略模式
需求:
收費系統 分別有三種收費方式: ①正常收費 ②打折收費 ③返利收費 客戶端發送(參數)到業務層,判斷參數屬於哪種收費模式,然後進行收費. 要求:用到單一設計原則,開閉原則. ==================================================================== 分析: 收費有各種收費方式,那麽可以將收費抽象出來,定義一個接口,以後出現哪種收費的時候,就實現收費接口. Charge(收費接口):定義一個抽象收費接口,讓子類去實現它。 NormalCharge(正常收費):/** * 收費接口 * @authorAdministrator * */ public interface Charge { /** * 收費 * @param chargeFormDto * @return */ double charge(ChargeFormDto chargeFormDto); }
NormalCharge(正常收費):
/** * 具體 正常收費策略 * @author Administrator * */ public class NormalCharge implements Charge { @Override public double charge(ChargeFormDto chargeFormDto) { System.out.println("正常收費: " + chargeFormDto.getPrice()); return chargeFormDto.getPrice(); } }
DiscountCharge(打折收費):
/** * 具體 打折收費策略類 * @author Administrator * */ public class DiscountCharge implements Charge { @Override public double charge(ChargeFormDto chargeFormDto) { double price = chargeFormDto.getPrice() - chargeFormDto.getPrice() * chargeFormDto.getRebate(); System.out.println("打折收費: " + price); return price; } }
RebateCharge(返利收費):
/** * 具體 返利消費策略類 * @author Administrator * */ public class RebateCharge implements Charge { @Override public double charge(ChargeFormDto chargeFormDto) { double price = chargeFormDto.getPrice() - chargeFormDto.getPrice() / chargeFormDto.getFullCash() * chargeFormDto.getReturnCash(); System.out.println("返利消費, 消費:" + chargeFormDto.getPrice() + ", 返利: " + price); return price; } }
ChargeFormDto(收費傳輸對象):
/** * 收費表單傳輸對象 * @author Administrator * */ public class ChargeFormDto implements Serializable { /** * 打折類型 */ private String type; /** * 總價 */ private double price; /** * 折扣 */ private double rebate; /** * 滿額度 */ private double fullCash; /** * 反額度 */ private double returnCash; public ChargeFormDto() { super(); } public ChargeFormDto(String type, double price, double rebate, double fullCash, double returnCash) { super(); this.type = type; this.price = price; this.rebate = rebate; this.fullCash = fullCash; this.returnCash = returnCash; } public String getType() { return type; } public void setType(String type) { this.type = type; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public double getRebate() { return rebate; } public void setRebate(double rebate) { this.rebate = rebate; } public double getFullCash() { return fullCash; } public void setFullCash(double fullCash) { this.fullCash = fullCash; } public double getReturnCash() { return returnCash; } public void setReturnCash(double returnCash) { this.returnCash = returnCash; } }
ChargeContext(處理收費的業務對象):
/** * 處理收費的Context (業務類) * @author Administrator * */ public class ChargeContext { /** * 收費接口 */ private Charge charge; /** * 收費傳輸對象 */ private ChargeFormDto dto; public ChargeContext(ChargeFormDto dto) { this.dto = dto; try { charge = (Charge) Class.forName(dto.getType()).newInstance(); } catch (Exception e) { e.printStackTrace(); } } /** * 返回收費結果 * @return */ public double account() { return charge.charge(dto); } }
ChargeClient(收費客戶端):
public class ChargeClient { public static void main(String[] args) { // 創建收費清單 ChargeFormDto dto = new ChargeFormDto(); dto.setType("edu.strategy.strategy.impl.NormalCharge"); // 輸入具體策略類的路徑 dto.setPrice(300); // 創建收費服務 ChargeContext context = new ChargeContext(dto); // 計算 context.account(); } }
運行結果:
收費類型那裏現在是寫具體類名,但是這樣不太方便,這裏可以優化,可以選擇讀取配置文件與萬能工廠的方式進行改進。
三、總結
優點:
1、易於擴展;策略模式提供了對 "開閉原則" 的完美支持,用戶可以在不修改原有系統的基礎上選擇算法或行為,也可以靈活地新增新的算法或行為。
2、策略類之間可以自由切換;由於策略類都實現同一個接口,所有使它們間可以自由切換
3、解耦;將算法的責任和本身進行解耦,使得算法可獨立使用外部而變化,客戶端方法根據外部條件選擇不同策略來解決不同的問題。
缺點:
1、客戶端必須指定所有的策略類,並自行決定使用哪一個策略類。
2、策略模式將造成上次很多策略類。
適用性:
適用於動態選擇多種負責行為:1、負責的算法/數據結構;2、類的行為/方法,提高行為的保密性。
設計模式學習筆記(三)——策略模式