演算法的封裝與切換——策略模式(三)
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 |
如果需要增加新的打折方式,原有程式碼均無須修改,只要增加一個新的折扣類作為抽象折扣類的子類,實現在抽象折扣類中宣告的打折方法,然後修改配置檔案,將原有具體折扣類類名改為新增折扣類類名即可,完全符合“開閉原則”。
相關推薦
演算法的封裝與切換——策略模式(三)
24.3 完整解決方案 為了實現打折演算法的複用,並能夠靈活地向系統中增加新的打折方式,Sunny軟體公司開發人員使用策略模式對電影院打折方案進行重構,重構後基本結構如圖24-2所示:
【Android架構】基於MVP模式的Retrofit2+RXjava封裝之檔案上傳(三)
最近手頭事比較多,抽個空把之前系列也補充一下。 先回顧下之前的 【Android架構】基於MVP模式的Retrofit2+RXjava封裝(一) 【Android架構】基於MVP模式的Retrofit2+RXjava封裝之檔案下載(二) 今天要說的是檔案上傳 1.單圖上
Unity3d與設計模式(三)工廠模式
這個系列的文章,並不會將所有用到的設計模式全部講一遍,事實上我個人認為,並不是所有的設計模式都適用於unity3d。這裡講的主要還是一些常用的設計模式。 那麼,本章講的就是常見的構建型模式當中的工廠模式。 簡單工廠模式 講工廠,首先得從簡單工廠說起。
複雜物件的組裝與建立——建造者模式(三)
8.4 關於Director的進一步討論 指揮者類Director在建造者模式中扮演非常重要的作用,簡單的Director類用於指導具體建造者如何構建產品,它按一定次序呼叫Builder的build
請求傳送者與接收者解耦——命令模式(三)
4 命令佇列的實現 有時候我們需要將多個請求排隊,當一個請求傳送者傳送一個請求時,將不止一個請求接收者產生響應,這些請求接收者將逐個執行業務方法,完成對請求的處理。此時,我們可以通過命令佇列
建造者模式-Builder Pattern 複雜物件的組裝與建立——建造者模式(三):關於Director的進一步討論,建造者模式總結
8.4 關於Director的進一步討論 指揮者類Director在建造者模式中扮演非常重要的作用,簡單的Director類用於指導具體建造者如何構建產品,它按一定次序呼叫Builder的build
JAVA設計模式(三)靜態與動態代理模式
代理模式:為某個物件提供一個代理,以控制對這個物件的訪問。 代理類和委託類有共同的父類或父介面,這樣在任何使用委託類物件的地方都可以用代理物件替代。代理類負責請求的預處理、過濾、將請求分派給委託類處理、以及委託類執行完請求後的後續處理。 通過上面的描述
設計模式面試與筆試題剖析(三)
Windows Media Player和RealPlayer是兩種常用的媒體播放器,它們的API結構和呼叫方法存在區別。現在你的應用程式需要支援這兩種播放器API,而且在將來可能還需要支援新的媒
設計模式之迭代器與組合模式(三)
現在我們已經能愉快地看著一頁一頁羅列出來的選單進行點菜了。現在又有的小夥伴希望能夠加上一份餐後甜點的“子選單”。怎麼辦呢?我們不僅僅要支援多個選單,甚至還要支援選單中的選單。 如果我們能讓甜點選單變成餐廳選單集合的一個元素,那該有多好。但是根據現在的實現,根本做不到呀。我們想要的是這樣的: 我們需要什麼
文件與目錄管理命令(三)
信息 touch share 單位換算 目錄管理類命令包括:cd,pwd,ls,mkdir,rmdir,tree,cp,mv,rm,touch,stat1.1.ls功能:列出文件或目錄命令幫助:man lsinfo lsls --helphelp cd #只有內部命令才能用ls /usr/s
Android BLE與終端通信(三)——client與服務端通信過程以及實現數據通信
.sh 沒有 indexof 實例 解析 rip listview filter @override Android BLE與終端通信(三)——client與服務端通信過程以及實現數據通信 前面的終究僅僅是小知識點。上不了臺面,也僅僅能算是起
java設計模式(三)模板模式
pro str pan style coff pub 調用 類定義 ted 抽象類中公開定義了執行它的方法的方式,子類可以按需求重寫方法實現,但調用將以抽象類中定義的方式進行,典型應用如銀行辦理業務流程、沖泡飲料流程。下面給出簡單例子,用沸水沖泡飲料,分為四步:將水煮沸
策略模式(Stratety)
over ide eat .com pat null console style col namespace StrategyPattern //策略模式 { /// <summary> /// 定義所以支持的算法的公共接口
設計模式(三)裝飾者模式Decorator
不知道 operation 總結 界面 都是 per @override stat override 裝飾者模式針對的問題是:對一個結構已經確定的類,在不改變該類的結構的情況下,動態增加一些功能。 一般來說,都是對一些已經寫好的架構增加自己的功能,或者應對多種情況,
Java IO 字節流與字符流 (三)
length 相關操作 數組 new throws mce 存在 () put Java的IO流分為字符流(Reader,Writer)和字節流(InputStream,OutputStream),字節流顧名思義字節流就是將文件的內容讀取到字節數組,然後再輸出到另一個文件
設計模式(三)---抽象工廠模式
ava des 模式 println 5.5 mage test 抽象工廠 urn 1、 簡介:為創建一組相關或相互依賴的對象提供一個接口,無需指定它們的具體類。抽象工廠模式通常是用於創創建一族產品,並且這族產品分不同的等級;不同的具體工廠類生產不同等級的一族產品。 2、
多線程:多線程設計模式(三):Master-Worker模式
fonts strong stat bre not 多線程 too () 部分 Master-Worker模式是常用的並行模式之一,它的核心思想是,系統有兩個進程協作工作:Master進程,負責接收和分配任務;Worker進程,負責處理子任務。當Worker進程將子任務處理
《神經網絡與深度學習》(三) 稀疏編碼
學習方法 深度學習 變體 復雜 鏈接 線性規劃 con images 叠代 轉自:http://www.cnblogs.com/caocan702/p/5666175.html 借鑒前人的文章鏈接 http://blog.csdn.net/zouxy09/article
設計模式(三) 工廠模式
初始化 重要 不能 還需 new 不同 參數 裏的 作用 概述: 屬於創建型設計模式,需要生成的對象叫做產品 ,生成對象的地方叫做工廠 。 使用場景: 在任何需要生成復雜對象的地方,都可以使用工廠方法模式。 直接用new可以完成的不需要用工廠模式 下面將介紹五種工廠
策略模式(C++)
type include name quic 構造 排序算法 插入 實現 pla 策略模式:把一系列算法封裝起來,使之可以相互替換。這樣就可以使算法獨立於客戶端變化。 如我們有很多排序算法,但是在不通的環境中,需要使用不同算法,那就可以定義一個抽象類,提供統一的接口