bridge模式和stradegy模式的區別
下邊三段分別來自CSDN論壇的貼子和一篇blogjava的文章,看了之後令我茅塞頓開,為表尊重不在冗述,直接貼原文了。
實際上所有模式可以只分為類模式和物件模式兩種,類模式是用繼承而物件模式是用委託
Bridge模式和Strategy模式相似就是因為他們都將任務委託給了另外一個介面的具體實現,
他們之間的區別在於Bridge的目的是讓底層實現和上層介面可以分別演化,從而提高移植性
而Strategy的目的是將複雜的演算法封裝起來,從而便於替換不同的演算法。
因此可以想象一般情況下Bridge的實現幾乎不會在執行時更改而Strategy的演算法則很有可能
需要在執行時更換,這就導致在細節方面需要考慮的因素可能會很不相同。
strategy模式是為了擴充套件和修改,並提供動態配置。它往往可以在同一環境當中使用不同的策略,就是呼叫不同的派生類。其內部實現是自由的,不受已有的類介面的限制(很多時候根本就不呼叫現成的介面)。
bridge模式是往往是為了利用已有的方法或類。它將原來不統一,不相容的介面封裝起來,變成統一的介面。它的應用往往是不同的環境或平臺下只能選擇一 種,比如說在windows平臺下只能用WinClass,而在unix平臺下只能用UnixClass.它的主要作用不是配置而是定義通用介面。
據個例子來說:我要畫園,要實心園,我可以用SolidPen來配置,畫虛線園可以用dashedPen來配置。這是strategy模式。
而同樣是畫園,我是在windows下來畫實心園,就用windowPen+solidPen來配置,在unix下畫實心園就用 unixPen+solidPen來配置。如果要再windows下畫虛線園,就用windowsPen+dashedPen來配置,要在unix下畫虛 線園,就用unixPen+dashedPen來配置。
我這裡僅僅是就一種情況來說strategy和bridge的組合應用,其他的組合可能性隨環境變化而多種多樣。從中可以看出,bridge和strategy是可能組合使用,側重不同方面的。
模式某種角度上來講就是物件組合。不要看他們都是物件組合就好像是一樣的。模式的動機,意圖,使用場合,組合方式,這些都是模式的一部分。其中細微的不同足以區分不同的模式。
橋接(Bridge)模式是結構型模式的一種,而策略(strategy)模式則屬於行為模式。以下是它們的UML結構圖。
在橋接模式中,Abstraction通過聚合的方式引用Implementor。
在策略模式中,Context也使用聚合的方式引用Startegy抽象介面。
從他們的結構圖可知,在這兩種模式中,都存在一個物件使用聚合的方式引用另一個物件的抽象介面的情況,而且該抽象介面的實現可以有多種並且可以替換。可以說兩者在表象上都是呼叫者與被呼叫者之間的解耦,以及抽象介面與實現的分離。
那麼兩者的區別體現在什麼地方呢?
1. 首先,在形式上,兩者還是有一定區別的,對比兩幅結構圖,我們可以發現,在橋接模式中不僅Implementor具有變化 (ConcreateImplementior),而且Abstraction也可以發生變化(RefinedAbstraction),而且兩者的變化 是完全獨立的,RefinedAbstraction與ConcreateImplementior之間鬆散耦合,它們僅僅通過Abstraction與 Implementor之間的關係聯絡起來。而在策略模式中,並不考慮Context的變化,只有演算法的可替代性。
2. 其次在語意上,橋接模式強調Implementor介面僅提供基本操作,而Abstraction則基於這些基本操作定義更高層次的操作。而策略模式強調 Strategy抽象介面的提供的是一種演算法,一般是無狀態、無資料的,而Context則簡單呼叫這些演算法完成其操作。
3. 橋接模式中不僅定義Implementor的介面而且定義Abstraction的介面,Abstraction的介面不僅僅是為了與 Implementor通訊而存在的,這也反映了結構型模式的特點:通過繼承、聚合的方式組合類和物件以形成更大的結構。在策略模式中,Startegy 和Context的介面都是兩者之間的協作介面,並不涉及到其它的功能介面,所以它是行為模式的一種。行為模式的主要特點就是處理的是物件之間的通訊方 式,往往是通過引入中介者物件將通訊雙方解耦,在這裡實際上就是將Context與實際的演算法提供者解耦。
所以相對策略模式,橋接模式要表達的內容要更多,結構也更加複雜。橋接模式表達的主要意義其實是介面隔離的原則,即把本質上並不內聚的兩種體系區別 開來,使得它們可以鬆散的組合,而策略在解耦上還僅僅是某一個演算法的層次,沒有到體系這一層次。從結構圖中可以看到,策略的結構是包容在橋接結構中的,橋 接中必然存在著策略模式,Abstraction與Implementor之間就可以認為是策略模式,但是橋接模式一般Implementor將提供一系 列的成體系的操作,而且Implementor是具有狀態和資料的靜態結構。而且橋接模式Abstraction也可以獨立變化。
Bridge 例子: Bridge遵循的是介面隔離原則的典型。如 JDBC, 我們都知道JDBC是使用Bridge模式進行設計的,DriverManager就是其中的Abstraction,java.sql.Driver是Implementor,com.mysql.jdbc.Driver是Implementor的一個具體實現(請參考GOF的Bridge模式的描述)。大家注意了,前一個Driver是一個介面,後者卻是一個類,它實現了前面的Driver介面。
還有 現在流行的DAO 介面規範
其他例子:
- abstract class Shape{
- public void draw();
- }
- //這裡業務出現了多種畫圖方式,DP1,DP2……
- //抽象出接口出DP1,DP2
- interface Drawing{
- public void drawLine();
- public void drawCircle();
- }
- class V1Drawing{
- public void drawLine(){};
- public void drawCircle(){};
- }
- class V2Drawing{
- public void drawLine(){};
- public void drawCircle(){};
- }
- //使用組合 ,聚集Drawing
- class Rectangle extends Shape{
- public void draw(Drawing dp){
- dp.drawLine();
- }
- }
- class Circle extends Shape{
- public void draw(Drawing dp){
- dp.drawCircle();
- }
- }
- //抽象類Shape的派生類,使用一組實現(DP1,DP2)的介面
- //使得派生類不依賴於一組具體的實現,從設計模式而言,這稱為Bridge模式
Stategy 例子:
首先,我們建立一個抽象類RepTempRule 定義一些公用變數和方法:
public abstract class RepTempRule{ protected String oldString=""; public void setOldString(String oldString){ this.oldString=oldString; } protected String newString=""; public String getNewString(){ return newString; } public abstract void replace() throws Exception; } |
在RepTempRule中 有一個抽象方法abstract需要繼承明確,這個replace裡其實是替代的具體方法.
我們現在有兩個字元替代方案,
1.將文字中aaa替代成bbb;
2.將文字中aaa替代成ccc;
對應的類分別是RepTempRuleOne RepTempRuleTwo
public class RepTempRuleOne extends RepTempRule{ |
public class RepTempRuleTwo extends RepTempRule{ public void replace() throws Exception{ newString=oldString.replaceFirst("aaa", "ccc") System.out.println("this is replace Two"); } } |
第二步:我們要建立一個演算法解決類,用來提供客戶端可以自由選擇演算法。
public class RepTempRuleSolve {
private RepTempRule strategy; public RepTempRuleSolve(RepTempRule rule){ public String getNewContext(Site site,String oldString) { public void changeAlgorithm(RepTempRule newAlgorithm) { } |
呼叫如下:
public class test{ ...... public void testReplace(){ //使用第一套替代方案 //使用第二套 solver=new RepTempRuleSolve(new RepTempRuleTwo()); } ..... } |
我們達到了在執行期間,可以自由切換演算法的目的。
實際整個Strategy的核心部分就是抽象類的使用,使用Strategy模式可以在使用者需要變化時,修改量很少,而且快速.
Strategy和Factory有一定的類似,Strategy相對簡單容易理解,並且可以在執行時刻自由切換。Factory重點是用來建立物件。
Strategy適合下列場合:
1.以不同的格式儲存檔案;
2.以不同的演算法壓縮檔案;
3.以不同的演算法截獲圖象;
4.以不同的格式輸出同樣資料的圖形,比如曲線 或框圖bar等