乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Bridge模式,Decorator模式

       木有銀 2008-08-01
      上一次主要介紹了幾個創(chuàng)建型的設(shè)計模式AbstractFactroy,F(xiàn)actoryMethod和Singliton。它們的共同的特點,都是用來創(chuàng)建對象的。這次接下來的內(nèi)容,涉及到的是幾個結(jié)構(gòu)型的模式。所謂結(jié)構(gòu)型模式,就是用來解決在創(chuàng)建系統(tǒng)結(jié)構(gòu)的過程中,通過對類或者對象進(jìn)行合理有效的組合,以獲得更大的結(jié)構(gòu)的方法。這兒主要講到了Bridge模式和Decorator模式。對于Bridge模式可能需要更多的理解,因為它在很大程度上說,例示了設(shè)計模式的基本的設(shè)計思路和原則。

      Bridge模式

      當(dāng)初Java剛剛推出來的時候,AWT可是一個比較熱的話題,雖然現(xiàn)在有被Swing取代的趨勢。但是我一直都覺得AWT也有其優(yōu)勢,至少它使用的本地代碼就要比Swing快上許多,而且,可以為用戶提供熟悉的本地操作系統(tǒng)界面。如果在Windows XP中運行基于AWT的程序的話,XP中絢爛多變的界面Theme可以輕易應(yīng)用到AWT程序中,而Swing就不行了,因為AWT所調(diào)用的是本帶代碼,使用的是本地的窗體控件。當(dāng)然,Swing也有其好處,不可一概而論。

      簡單來講,AWT提供對程序員的是對窗體界面系統(tǒng)的抽象,而在內(nèi)部實現(xiàn)中,針對每一種操作系統(tǒng),分別有不同實現(xiàn),這就是同位體(Peer)的概念。當(dāng)程序員調(diào)用AWT對象時,調(diào)用被轉(zhuǎn)發(fā)到對象所對應(yīng)的一個Peer上,在由Peer調(diào)用本地對象方法,完成對象的顯示。例如,如果你使用AWT創(chuàng)建了一個Menu類的實例,那么在程序運行時會創(chuàng)建一個菜單同位體的實例,而由創(chuàng)建的同位體的來實際執(zhí)行菜單的現(xiàn)實和管理。不同的系統(tǒng),有不同的同位體實現(xiàn),Solaris JDK將產(chǎn)生一個Motif菜單的同位體,Windows下的JDK將產(chǎn)生一個Windows的菜單的同位體,等等。同位體的使用,使得交叉平臺窗口工具的開發(fā)變得極為迅速,因為同位體的使用可以避免重新實現(xiàn)本地窗口控件中已經(jīng)包含的方法。


      圖九:AWT中的組件和其對等體
      圖九:AWT中的組件和其對等體

      實際上,從設(shè)計的角度來看,這是一個抽象和實現(xiàn)分離的過程--AWT是抽象,同位體是實現(xiàn),抽象和實現(xiàn)各自成為一個對象體系,它們由一個橋連接起來,可以各自發(fā)展各自的對象層次,而不必顧慮另一方面。這就是Bridge模式所提供的思想。Bridge模式更可以提供在各個不同的實現(xiàn)中動態(tài)的進(jìn)行切換,而不必從新編譯程序。

      通常,Bridge模式和AbstractFactory模式一起工作,由AbstractFactory來創(chuàng)建一個具體實現(xiàn)的對象體系。特殊的,當(dāng)只有一個實現(xiàn)的時候,可以將Implementor抽象類去掉。這樣,在抽象和實現(xiàn)之間建立起了一一對應(yīng)的關(guān)系,但這并不損害Bridge模式的內(nèi)涵。這被稱為退化了的Bridge模式。

      很多時候,Abstraction層次和Implementor層次之間的方法都不是一一對應(yīng)的,也就是說,在Abstraction和Implementor之不是簡單的的消息轉(zhuǎn)發(fā)。通常,我們會將Abstraction作為一個抽象類(而不是接口)來實現(xiàn)。在Implementor層次中定義底層的,或者稱之為原子方法,而在Abstraction層次中定義一些中高層的基于原子方法的抽象方法。這樣,就能更為清晰的劃分Abstraction和Implementor,類的結(jié)構(gòu)也更為清晰。


      圖十:Bridge模式對系統(tǒng)的劃分
      圖十:Bridge模式對系統(tǒng)的劃分

      下面,我們來看一個Bridge模式的具體應(yīng)用??紤]這樣的一個問題,需要生成一份報告,但是報告的格式并沒有確定,可能是HTML文件,也可能是純ASCII文本。報告本身也可能分為很多種,財務(wù)報表,貨物報表,等等問題很簡單,用繼承也較容易實現(xiàn),因為相互之間的組合關(guān)系并不是很多。但是,我們現(xiàn)在需要用Bridge的觀點來看問題。

      在Bridge模式中,使用一個Report類來描敘一個報告的抽象,用一個Reporter類來描敘Report的實現(xiàn),它的子類有HTMLReporter和ASCIIReporter,用來分別實現(xiàn)HTML格式和ASCII格式的報告。在Report層次下面,有具體的一個StockListReport子類,用來表示貨物清單報告。

      public abstract class Report
                  {
                  Reporter reporter;
                  public Report(Reporter reporter) {
                  this.reporter = reporter;
                  }
                  //抽象類使用橋接對象的方法來實現(xiàn)一個任務(wù)
                  public void addReportItem(Object item){
                  reporter.addLine(item.toString());
                  }
                  public void addReportItems(List items){
                  Iterator iterator = items.iterator();
                  while ( iterator.hasNext() )
                  {
                  reporter.addLine(iterator.next().toString());
                  }
                  }
                  public String report(){
                  return reporter.getReport();
                  }
                  }
                  public class StockListReport extends Report{
                  ArrayList stock=new ArrayList();
                  public StockListReport(Reporter reporter){
                  super(reporter);
                  }
                  public void addStockItem(StockItem stockItem){
                  stock.add(stockItem);
                  addReportItem(stockItem);
                  }
                  }
                  //實現(xiàn)層次的抽象父類定義原子方法,供抽象層次的類調(diào)用
                  public abstract class Reporter{
                  String header = "";
                  String trailer = "";
                  String report = "";
                  public abstract void addLine(String line);
                  public void setHeader(String header){
                  this.header = header;
                  }
                  public void setTrailer(String trailer){
                  this.trailer = trailer;
                  }
                  public String getReport(){
                  return header+report+trailer;
                  }
                  }
                  public class HTMLReporter extends Reporter{
                  public HTMLReporter(){
                  setHeader("<HTML>\n<HEAD></HEAD>\n<BODY>\n");
                  setTrailer("</BODY>\n</HTML>");
                  }
                  public void addLine(String line){
                  report += line + "<BR>\n";
                  }
                  }
                  public class ASCIIReporter extends Reporter{
                  public void addLine(String line) {
                  report += line + "\n";
                  }
                  }
                  

      實際上,Bridge模式是一個很強大的模式,可以應(yīng)用在很多方面。其基本思想:分離抽象和實現(xiàn),是設(shè)計模式的基礎(chǔ)之一。正如GOF所提到的:"找到變化的部分,并將其封裝起來";"更多的考慮用對象組合機制,而不是用對象繼承機制"。Bridge模式很好的體現(xiàn)了這幾點。





      回頁首


      Decorator模式

      在使用Java中的IO類庫的時候,是不是快要被它那些功能相似,卻又絕對可稱得上龐雜的類搞得要發(fā)瘋了?或許你很不明白為什么要做這么多功能相似的幾十個類出來,這就是Decorator模式將要告訴你的了。

      在IO處理中,Java將數(shù)據(jù)抽象為流(Stream)。在IO庫中,最基本的是InputStream和OutputStream兩個分別處理輸出和輸入的對象(為了敘述簡便起見,這兒只涉及字節(jié)流,字符流和其完全相似),但是在InputStream和OutputStream中之提供了最簡單的流處理方法,只能讀入/寫出字符,沒有緩沖處理,無法處理文件,等等。它們只是提供了最純粹的抽象,最簡單的功能。

      如何來添加功能,以處理更為復(fù)雜的事情呢?你可能會想到用繼承。不錯,繼承確實可以解決問題,但是繼承也帶來更大的問題,它對每一個功能,都需要一個子類來實現(xiàn)。比如,我先實現(xiàn)了三個子類,分別用來處理文件,緩沖,和讀入/寫出數(shù)據(jù),但是,如果我需要一個既能處理文件,又具有緩沖功能的類呢?這時候又必須在進(jìn)行一次繼承,重寫代碼。實際上,僅僅這三種功能的組合,就已經(jīng)是一個很大的數(shù)字,如果再加上其它的功能,組合起來的IO類庫,如果只用繼承來實現(xiàn)的話,恐怕你真的是要被它折磨瘋了。


      圖六:JDK中IO流的類層次
      圖六:JDK中IO流的類層次

      Decorator模式可以解決這個問題。Decorator字面的意思是裝飾的意思,在原有的基礎(chǔ)上,每添加一個裝飾,就可以增加一種功能。這就是Decorator的本意。比如,對于上面的那個問題,只需要三個Decorator類,分別代表文件處理,緩沖和數(shù)據(jù)讀寫三個功能,在此基礎(chǔ)上所衍生的功能,都可以通過添加裝飾來完成,而不必需要繁雜的子類繼承了。更為重要的是,比較繼機制承而言,Decorator是動態(tài)的,可以在運行時添加或者去除附加的功能,因而也就具有比繼承機制更大的靈活性。

      上面就是Decorator的基本思想,下面的是Decorator模式的靜態(tài)結(jié)構(gòu)圖:


      圖七:Decorator模式的類圖
      圖七:Decorator模式的類圖

      可以看到,一個Decorator與裝飾的Subject對象有相同的接口,并且除了接口中給出的方法外,每個Decorator均有自己添加的方法,來添加對象功能。每個Decorator均有一個指向Subject對象的引用,附加的功能被添加在這個Subject對象上。而Decorator對象本身也是一個Subject對象,因而它也能夠被其他的Decorator所修飾,提供組合的功能。

      在Java IO操作中,經(jīng)??梢钥吹街T如如下的語句:

      myStringBuffer=new StringBuffer("This is a sample string to be read");
                  FilterInputStream myStream=new LineNumberInputStream
                  ( new BufferInputStream( new StringBufferInputStream( myStringBuffer)));
                  myStream.read();
                  myStream.line();
                  

      多個的Decorator被層疊在一起,最后得到一個功能強大的流。既能夠被緩沖,又能夠得到行數(shù),這就是Decorator的威力!

      不僅僅如此,Java中的IO還允許你引入自定義的Decorator,來實現(xiàn)自己想要的功能。在良好的設(shè)計背景下,這做起并不復(fù)雜,只需要4步:

      1. 創(chuàng)建兩個分別繼承了FilterInputStream和 FilterOutputStream的子類
      2. 重載read()和write()方法來實現(xiàn)自己想要的功能。
      3. 可以定義或者重載其它方法來提供附加功能。
      4. 確定這兩個類會被一起使用,因為它們在功能上是對稱的。

      就這樣,你就可以無限的擴展IO的功能了。

      在了解了IO中的Decorator后,我們再來看一個Decorator模式應(yīng)用的具體的例子。這個例子原本是出現(xiàn)在GOF書中的,這兒稍作改動,引來示例。

      在一個圖形用戶界面(GUI)中,一個組件有時候需要用到邊框或者滾動條,而有時候又不需要,有時候可能兩者都要用到。當(dāng)需要動態(tài)的去處或者添加職能的時候,就可以考慮使用Decorator模式了。這兒對于一個VisualComponent組件對象,我們引入了兩個Decorator類:BoderDecorator和ScrollDecorator,分別用來為組件添加邊框和處理滾動。程序類圖如下:


      圖八:Decorator模式的應(yīng)用例子
      圖八:Decorator模式的應(yīng)用例子

      程序?qū)懙煤芎唵?,沒有包括具體的代碼,只是有一個可以運行的框架以供參考。代碼如下:

      //Client類用來創(chuàng)建窗體和組件對象,這兒可以看到Decorator是如何組合和應(yīng)用的
                  class Client{
                  public static void main (String[] args ){
                  Window   window   = new Window ();
                  TextView textView = new TextView ();
                  window.setContents (
                  new BorderDecorator (
                  new ScrollDecorator (textView, 500), 1));
                  }
                  }
                  //Windows類用來容納組件對象
                  class Window{
                  VisualComponent contents;
                  public Window () {}
                  public void setContents (VisualComponent vc){
                  contents = vc;
                  }
                  }
                  //VisualComponent類定義了組件的接口
                  class VisualComponent{
                  public VisualComponent (){}
                  public void draw (){}
                  public void resize (){}
                  }
                  //TextView類是一個顯示文本的具體的組件
                  class TextView extends VisualComponent{
                  public TextView (){}
                  public void draw (){
                  …
                  }
                  public void resize (){
                  …
                  }
                  }
                  //Decorator類繼承于VisualComponent,定義所有Decorator的缺省方法實現(xiàn)
                  class Decorator extends VisualComponent{
                  private VisualComponent component;
                  public Decorator (VisualComponent vc) {
                  this.component=vc;
                  }
                  public void draw () {
                  component.draw ();
                  }
                  public void resize () {
                  component.resize ();
                  }
                  }
                  //BorderDecorator類為組件提供邊框
                  class BorderDecorator extends Decorator{
                  private int width;
                  public BorderDecorator (VisualComponent vc, int borderWidth){
                  super (vc);
                  width = borderWidth;
                  }
                  public void draw (){
                  super.draw ();
                  drawBorder (width);
                  }
                  private void drawBorder (int width){
                  …
                  }
                  }
                  //ScrollDecorator類為組件提供滾動條
                  class ScrollDecorator extends Decorator{
                  private int scrollSize;
                  public ScrollDecorator (VisualComponent vc, int scrSize){
                  super (vc);
                  scrollSize = scrSize;
                  }
                  public void draw (){
                  scroll();
                  super.draw ();
                  }
                  private void scroll (){
                  …
                  }
                  }

      Decorator確實能夠很好的緩解當(dāng)功能組合過多時子類繼承所能夠帶來的問題。但是在得到很大的靈活性的同時,Decorator在使用時也表現(xiàn)得較為復(fù)雜??纯磧H僅為了得到一個IO流,除了要創(chuàng)建核心的流外,還要為其加上各種各樣的裝飾類,這使得代碼變得復(fù)雜而難懂。有幾個人一開始時沒有被Java的IO庫嚇一跳呢?

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多