1. 程式人生 > >演算法的封裝與切換——策略模式(三)

演算法的封裝與切換——策略模式(三)

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   策略模式:把一系列算法封裝起來,使之可以相互替換。這樣就可以使算法獨立於客戶端變化。   如我們有很多排序算法,但是在不通的環境中,需要使用不同算法,那就可以定義一個抽象類,提供統一的接口