熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

老生常談:橋接模式

2022-06-13   來源: .NET編程 
    對於B/S架構來說我一直想結合實際開發環境來學習設計模式感覺這樣印象會更加深起碼你知道在什麼場合下應用它之前也寫過十多篇設計模式的文章之所以沒有寫完主要因為經驗不夠感覺不到其它設計模式在B/S架構中的應用場合和威力這篇我用橋接模式實現一個圖書銷售後計算最終售價的模塊

  假想案例說明出版社在出版的書後會在多家書店銷售假如所有的書的銷售都由一個總公司負責銷售它可以控制書的銷售方式例如計算機書打八折生活類的打七折等同時公司可以選擇地區經銷商做為二級代理二級代理都必須服從公司的促銷方式如果公司打折二級代理也要打折否則二級代理不能私自打折同時總公司會根據二級代理的銷售業績分為不同的二級代理例如鑽石黃金VIP等它們在得到的回扣上會有不同
 
      需要的知識開-閉原則(OCP)以及組合/聚合復用原則(CARP)至於組合模式可以參考這篇文章老生常談:組合模式

  結構圖這裡我用圖書銷售價格計算模塊來具體說明並不是標准圖

       

  橋接模式的定義【GOF】橋梁模式的用意是將抽象化(Abstraction)與實現化(Implementation)脫耦使得二者可以獨立地變化這句話有三個關鍵詞也就是抽象化實現化和脫耦

  抽象化存在於多個實體中的共同的概念性聯系就是抽象化作為一個過程抽象化就是忽略一些信息從而把不同的實體當做同樣的實體對待【LISKOV可以是接口也可以是抽象類用來定義一系列的操作定義

  實現化抽象化給出的具體實現就是實現化也是平常說的具體類負責實現抽象類或者是接口定義的方法等

  脫耦所謂耦合就是兩個實體的行為的某種強關聯而將它們的強關聯去掉就是耦合的解脫或稱脫耦在這裡脫耦是指將抽象化和實現化之間的耦合解脫開或者說是將它們之間的強關聯改換成弱關聯將兩個角色之間的繼承關系改為聚合關系就是將它們之間的強關聯改換成為弱關聯因此橋梁模式中的所謂脫耦就是指在一個軟件系統的抽象化和實現化之間使用組合/聚合關系而不是繼承關系從而使兩者可以相對獨立地變化可以看出這個系統含有兩個等級結構也就是

  )由抽象化角色和修正抽象化角色組成的抽象化等級結構 在結構圖上由抽象化角色book修正抽象化角色lifebook和computerbook構成
               )由實現化角色和兩個具體實現化角色所組成的實現化等級結構在結構圖上由diamondProxygoldProxyVIPProxy構成
       橋梁模式所涉及的角色這裡為了看的清楚些我加上各部分的示例代碼

  :抽象化(Abstraction)角色抽象化給出的定義並保存一個對實現化對象的引用


abstract  public class book
    {
        abstract public double promotionPrice();
        public  proxy _proxy;
        /// <summary>
        /// 圖書名稱
        /// </summary>
        public string bookName
        {
            get;
            set;
        }
    } 
           :修正抽象化(Refined Abstraction)角色擴展抽象化角色改變和修正父類對抽象化的定義
public class computerBook:book 
    {
        /// <summary>
        /// 計算機圖書打八折
        /// </summary>
        /// <param name=bookPrice>圖書原價</param>
        /// <returns>經過圖書正常打折以及代理商後的價格</returns>
        public override double  promotionPrice()
        {
            //throw new NotImplementedException();
            bookPrice = bookPrice * ;
            bookPrice = base_proxyproxyPrice(bookPrice);
            return bookPrice;
        }
        /// <summary>
        /// 圖書價格
        /// </summary>
        double bookPrice;
        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name=_bookPrice></param>
        public computerBook(double _bookPrice)
        {
            thisbookPrice = _bookPrice;
            basebookName = C#入門經典;      
        }      
    }
          :實現化(Implementor)角色這個角色給出實現化角色的接口但不給出具體的實現必須指出的是這個接口不一定和抽象化角色的接口定義相同實際上這兩個接口可以非常不一樣實現化角色應當只給出底層操作而抽象化角色應當只給出基於底層操作的更高一層的操作
abstract  public class proxy
    {
        abstract public double proxyPrice(double promotionPrice);
        /// <summary>
        /// 代理商名稱
        /// </summary>
        public string proxyName
        {
            get;
            set;
        }
        /// <summary>
        /// 代理商級別
        /// </summary>
        public string proxyTye
        {
            get;
            set;
        }
    }
          :具體實現化(Concrete Implementor)角色這個角色給出實現化角色接口的具體實現
public class diamondProxy:proxy 
    {
        /// <summary>
        /// 鑽石級代理商的價格為圖書正常打完折後的價格的八折
        /// </summary>
        /// <param name=promotionPrice></param>
        /// <returns></returns>
        public override double proxyPrice(double promotionPrice)
        {
            return promotionPrice * ;
        }
        //decimal promotionPrice;
        public diamondProxy()
        {
            baseproxyName = 北京代理;
            baseproxyTye = 鑽石代理;
        }
    }


           代碼以及結構圖分析可以看出在橋接模式中使用了組合模式如果不用組合模式呢當然也就不是橋接了下面的結構圖是用繼承實現的方案在結構圖中有一個總的計算價格的接口IBook下面是兩種打折方案的子類接IPromotionIProxy

  使用繼承的結構圖如下

  

  使用繼承的代碼如下


interface IBook
    {
        /// <summary>
        /// 圖書的價格接口
        /// </summary>
        /// <returns></returns>
        double price();
    }
interface IPromotion:IBook 
    {
        /// <summary>
        /// 圖書正常打折後的價格接口
        /// </summary>
        /// <returns></returns>
        double promotionPrice();
    }
interface IProxy:IBook 
    {
        /// <summary>
        /// 代理商打折後的價格接口
        /// </summary>
        /// <returns></returns>
        double proxyPrice();
    }
public class computerBook:IPromotion 
    {
        /// <summary>
        /// 計算機圖書打八折後的價格
        /// </summary>
        /// <returns></returns>
        public double promotionPrice()
        {
            return bookprice * 
        }
        double bookprice;
        public computerBook(double _bookprice)
        {
            thisbookprice = _bookprice;
        }
        /// <summary>
        /// 返回打折後的圖片價格
        /// </summary>
        /// <returns></returns>
        public double price()
        {
            return thispromotionPrice();
        }
    }
public class diamondProxy:IProxy 
    {
        /// <summary>
        /// 鑽石代理商打八折後的價格
        /// </summary>
        /// <returns></returns>
        public double proxyPrice()
        {
            return bookprice * 
        }
        double bookprice;
        public diamondProxy(double _bookprice)
        {
            thisbookprice = _bookprice;
        }
        /// <summary>
        /// 返回打折後的圖片價格
        /// </summary>
        /// <returns></returns>
        public double price()
        {
            return thisproxyPrice();       
        }
    }

  橋接與使用繼承的比較

  :在接口數量上來看橋接要少一個繼承用了三個

  從客戶端調用程序來看可以看出橋接模式要簡潔的多

  ):使用橋接的客戶端調用


//圖書類型:計算機打折為八折
            //原始價格:RMB
            //代理商級別鑽石打折為八折
            //計算最後實際等到的金額
            book _Book = new computerBook();           
            _Book_proxy = new diamondProxy();
            double proxyPrice = _BookpromotionPrice();

  ):使用繼承的客戶端調用


//實例化一本計算機圖書
            IBook _Book = new computerBook();
            //得到計算機打完折後的價格
            double price = _Bookprice();
            //實例化一位鑽石代理商
            IBook _BookProxy = new diamondProxy(price);
            //把正常打折後的圖片價格做為基數來計算最終價格
            price = _BookProxyprice();

  從兩者的業務邏輯代碼來看顯然是橋接模式精簡不少起碼在代碼量上是這樣
      橋梁模式適用場合根據上面的分析在以下的情況下應當使用橋梁模式

  如果一個系統需要在構件的抽象化角色和具體化角色之間增加更多的靈活性避免在兩個層次之間建立靜態的聯系 
          設計要求實現化角色的任何改變不應當影響客戶端或者說實現化角色的改變對客戶端是完全透明的 
          一個構件有多於一個的抽象化角色和實現化角色系統需要它們之間進行動態耦合

  總結本文通過一個具體的書店銷售圖書中計算圖書最終價格模塊來說明橋接模式的應用系統可以輕松的在圖書打折方式和代理商之間擴展及維護


From:http://tw.wingwit.com/Article/program/net/201311/13377.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.