演算法的封裝與切換——策略模式(三)
24.3 完整解決方案
為了實現打折演算法的複用,並能夠靈活地向系統中增加新的打折方式,Sunny軟體公司開發人員使用策略模式對電影院打折方案進行重構,重構後基本結構如圖24-2所示:
在圖24-2中,MovieTicket充當環境類角色,Discount充當抽象策略角色,StudentDiscount、 ChildrenDiscount 和VIPDiscount充當具體策略角色。完整程式碼如下所示:
//電影票類:環境類
class MovieTicket {
private double price;
private Discount discount; //維持一個對抽象折扣類的引用
public void setPrice(double price) {
this.price = price;
}
//注入一個折扣類物件
public void setDiscount(Discount discount) {
this.discount = discount;
}
public double getPrice() {
//呼叫折扣類的折扣價計算方法
return discount.calculate(this.price);
}
}
//折扣類:抽象策略類
interface Discount {
public double calculate(double price);
}
//學生票折扣類:具體策略類
class StudentDiscount implements Discount {
public double calculate(double price) {
System.out.println("學生票:");
return price * 0.8;
}
}
//兒童票折扣類:具體策略類
class ChildrenDiscount implements Discount {
public double calculate(double price) {
System.out.println("兒童票:");
return price - 10;
}
}
//VIP會員票折扣類:具體策略類
class VIPDiscount implements Discount {
public double calculate(double price) {
System.out.println("VIP票:");
System.out.println("增加積分!");
return price * 0.5;
}
}
為了提高系統的靈活性和可擴充套件性,我們將具體策略類的類名儲存在配置檔案中,並通過工具類XMLUtil來讀取配置檔案並反射生成物件,XMLUtil類的程式碼如下所示:
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
class XMLUtil {
//該方法用於從XML配置檔案中提取具體類類名,並返回一個例項物件
public static Object getBean() {
try {
//建立文件物件
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
doc = builder.parse(new File("config.xml"));
//獲取包含類名的文字節點
NodeList nl = doc.getElementsByTagName("className");
Node classNode=nl.item(0).getFirstChild();
String cName=classNode.getNodeValue();
//通過類名生成例項物件並將其返回
Class c=Class.forName(cName);
Object obj=c.newInstance();
return obj;
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
}
在配置檔案config.xml中儲存了具體策略類的類名,程式碼如下所示:
<?xml version="1.0"?>
<config>
<className>StudentDiscount</className>
</config>
編寫如下客戶端測試程式碼:
class Client {
public static void main(String args[]) {
MovieTicket mt = new MovieTicket();
double originalPrice = 60.0;
double currentPrice;
mt.setPrice(originalPrice);
System.out.println("原始價為:" + originalPrice);
System.out.println("---------------------------------");
Discount discount;
discount = (Discount)XMLUtil.getBean(); //讀取配置檔案並反射生成具體折扣物件
mt.setDiscount(discount); //注入折扣物件
currentPrice = mt.getPrice();
System.out.println("折後價為:" + currentPrice);
}
}
編譯並執行程式,輸出結果如下:
原始價為:60.0 --------------------------------- 學生票: 折後價為:48.0 |
如果需要更換具體策略類,無須修改原始碼,只需修改配置檔案,例如將學生票改為兒童票,只需將儲存在配置檔案中的具體策略類StudentDiscount改為ChildrenDiscount,如下程式碼所示:
<?xml version="1.0"?>
<config>
<className>ChildrenDiscount</className>
</config>
重新執行客戶端程式,輸出結果如下:
原始價為:60.0 --------------------------------- 兒童票: 折後價為:50.0 |
如果需要增加新的打折方式,原有程式碼均無須修改,只要增加一個新的折扣類作為抽象折扣類的子類,實現在抽象折扣類中宣告的打折方法,然後修改配置檔案,將原有具體折扣類類名改為新增折扣類類名即可,完全符合“開閉原則”。
【作者:劉偉 http://blog.csdn.net/lovelion】
相關文章
- 三種工廠模式與策略模式模式
- ToolBar封裝策略封裝
- 策略模式、策略模式與Spring的碰撞模式Spring
- redis sentinel哨兵模式安裝部署和切換Redis模式
- iOS 封裝頁數控制,點選NavigationTabBar切換頁面iOS封裝NavigationtabBar
- win10怎麼切換到桌面模式_win10平板模式和桌面模式的切換教程Win10模式
- 模板方法模式-封裝一套演算法流程模式封裝演算法
- 如何實現一個地相簿封裝,可以快速切換地圖封裝地圖
- 設計模式(三)Animation中的策略模式設計模式
- Win10怎樣切換平板模式_win10如何切換到平板模式Win10模式
- Java(三)封裝Java封裝
- win10安全模式切換正常模式的方法Win10模式
- 快速切換至Kotlin for Android模式KotlinAndroid模式
- EDBPPAS(Oracle相容版)Oracle與PostgreSQL相容模式的引數配置切換OracleSQL模式
- 策略模式與模板方法模式模式
- if else與策略模式模式
- EDB PPAS(Oracle 相容版) Oracle與PostgreSQL 相容模式的引數配置切換OracleSQL模式
- Skyline基本操作模式封裝模式封裝
- KindEditor如何切換成簡單模式??模式
- Linux下jdk的安裝解除安裝切換LinuxJDK
- 委派模式與策略模式記錄模式
- Dozer封裝物件或List的轉換封裝物件
- git建立與切換分支Git
- Oracle資料庫歸檔模式的切換ELOracle資料庫模式
- 微星筆記本怎麼切換啟動模式?微星筆記本bios設定啟動模式切換的教程筆記模式iOS
- 設計模式大冒險第三關:工廠模式,封裝和解耦你的程式碼設計模式封裝解耦
- 代理IP常見的三種切換方式
- axios封裝以及前端介面處理策略iOS封裝前端
- javascript設計模式與開發實踐(二)- 封裝和原型模式JavaScript設計模式封裝原型
- 深色模式適配和主題切換模式
- 網頁黑夜模式白天模式切換 html+css+js網頁模式HTMLCSSJS
- 三高Mysql - 搭建“三高”架構之擴充套件與切換MySql架構套件
- 十五、類與封裝的概念封裝
- laravel Es的封裝與使用Laravel封裝
- java三大特性-封裝Java封裝
- Go 實現常用設計模式(三)策略模式Go設計模式
- SPI機制與策略模式模式
- 使用 Repository 設計模式封裝通用的 CURD設計模式封裝
- Android從零擼美團(三) – Android多標籤tab滑動切換 – 自定義View快速實現高度定製封裝AndroidView封裝