<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理
        其實我這系列小文,名為源碼分析,其實是自己讀《設計模式》的讀書筆記。Decorator模式在java的IO庫中得到應用,java的IO庫看起來復雜,其實理解了Decorator模式再回頭看可以很好理解并使用。
        Decorator模式,也就是裝飾器模式,是對象結構型模式之一。

    1.意圖:動態地給一個對象添加一些額外的職責。給對象添加功能,我們首先想到的是繼承,但是如果每增一個功能都需要繼承,類的繼承體系將無可避免地變的龐大和難以理解。面向對象設計的原則:優先使用組合,而非繼承,繼承的層次深度最好不過三。

    2.適用場景:
    1)在不影響其他對象的情況下,以動態、透明的方式給單個對象添加額外的責任
    2)處理可以撤銷的職責
    3)為了避免類的數目爆炸,或者不能采用生成子類的方法進行擴展時

    3.UML圖和協作:



    Component——定義一個對象接口,可以給這些對象動態地添加職責

    ConcreteComponent——定義一個對象,可以給這個對象添加職責

    Decorator——維持一個指向Component的引用,并定義一個與Component一致的接口,作為裝飾類的父類

    ConcreteDecorator——具體裝飾類

    4.效果:
    1)與靜態繼承相比,Decorator可以動態添加職責,更為靈活
    2)避免產生復雜的類,通過動態添加職責,而不是一次性提供一個萬能的接口
    3)缺點是將產生比較多的小對象,對學習上有難度,顯然,java.io就是這個問題

    我們以一個例子來實現Decorator模式,假設這樣一個場景:在某個應用中需要打印票據,我們寫了一個PrintTicket接口,然后提供一個實現類(DefaultPrintTicket)實現打印的功能:

    package com.rubyeye.design_pattern.decorator;
    //抽象component接口
    public interface PrintTicket {
        
    public void print();
    }


    //默認實現類,打印票據
    package com.rubyeye.design_pattern.decorator;

    public class DefaultPrintTicket implements PrintTicket {

        
    public void print() {
            System.out.println(
    "ticket body");
        }

    }

    OK,我們的功能已經實現,我們還體現了針對接口編程的原則,替換一個新的打印方式很靈活,但是客戶開始提需求了——人生無法避免的三件事:交稅、死亡和需求變更。客戶要求打印頁眉,你首先想到的是繼承:
    package com.rubyeye.design_pattern.decorator;

    public class AnotherPrintTicket implements PrintTicket {

        
    public void print() {
            System.out.println(
    "ticket header");
            System.out.println(
    "ticket body");
        }

    }

    請注意,我們這里只是簡單的示例,在實際項目中也許意味著添加一大段代碼,并且需要修改打印票據本體的功能。需求接踵而至,客戶要求添加打印頁碼,要求增加打印花紋,要求可以聯打......你的類越來越龐大,直到你看見這個類都想吐的地步!-_-。讓我們看看另一個方案,使用Decorator模式來動態地給打印增加一些功能,首先是實現一個Decorator,它需要保持一個到PrintTicket接口的引用:

    package com.rubyeye.design_pattern.decorator;

    public class PrintTicketDecorator implements PrintTicket {

        
    protected PrintTicket printTicket;

        
    public PrintTicketDecorator(PrintTicket printTicket) {
            
    this.printTicket = printTicket;
        }

        
    //默認調用PrintTicket的print
        public void print() {
            printTicket.print();
        }

    }

    然后,我們實現兩個具體的裝飾類——打印頁眉和頁腳:
    package com.rubyeye.design_pattern.decorator;

    public class HeaderPrintTicket extends PrintTicketDecorator {

        
    public HeaderPrintTicket(PrintTicket printTicket){
            
    super(printTicket);
        }
        
        
    public void print() {
            System.out.println(
    "ticket header");
            
    super.print();
        }
    }

    package com.rubyeye.design_pattern.decorator;

    public class FooterPrintTicket extends PrintTicketDecorator {
        
    public FooterPrintTicket(PrintTicket printTicket) {
            
    super(printTicket);
        }

        
    public void print() {
            
    super.print();
            System.out.println(
    "ticket footer");
        }
    }

        使用起來也很容易:
       
    package com.rubyeye.design_pattern.decorator;

    public class DecoratorTest {

        
    /**
         * 
    @param args
         
    */
        
    public static void main(String[] args) {
            PrintTicket print
    =new HeaderPrintTicket(new FooterPrintTicket(new DefaultPrintTicket()));
            print.print();
        }

    }

    輸出:
    ticket header
    ticket body
    ticket footer

        了解了Decorator模式,我們聯系了下JUnit里面的應用。作為一個測試框架,應該方便地支持二次開發,也許用戶開發自己的TestCase,添加自定義的功能,比如執行重復測試、多線程測試等等。動態添加職責,而又不想使用靜態繼承,這正是Decorator使用的地方。在junit.extensions包中有一個TestDecorator,正是所有裝飾類的父類,也是作為二次開發的基礎,它實現了Test接口,而Test接口就是我們定義的抽象接口:
    public class TestDecorator implements  Test {
        
    //保有一個指向Test的引用
            protected Test fTest;
           
        
    public TestDecorator(Test test) {
            fTest
    = test;
        }
            
            
    public void basicRun(TestResult result) {
              fTest.run(result);
            }
            
    public void run(TestResult result) {
               basicRun(result);
            }
            
    }

    Junit已經提供了兩個裝飾類:junit.extensions.ActiveTest用于處理多線程,junit.extensions.RepeatedTest用于執行重復測試,看看RepeatedTest是怎么實現的:
    public class RepeatedTest extends  TestDecorator {
            
    //重復次數
        private int fTimesRepeat;

        
    public RepeatedTest(Test test, int repeat) {
            
    super(test);
            fTimesRepeat
    = repeat;
        }
            
    public void run(TestResult result) {
            
    //重復執行
                    for (int i= 0; i < fTimesRepeat; i++) {
                
    if (result.shouldStop())
                    
    break;
                
    super.run(result);
            }
        }
            
    }

        RepeatedTest繼承TestDecorator ,覆寫run(TestReult result)方法,重復執行,super.run(result)將調用傳入的TestCase的run(TestResult result)方法,這已經在TestDecorator默認實現。看看使用方式,使用裝飾模式的好處不言而喻。

    TestSuite suite = new TestSuite();
    suite.addTest(
    new TestSetup(new RepeatedTest(new Testmath("testAdd"),12)));


    評論

    # re: JUnit源碼分析(四)——從Decorator模式說起  回復  更多評論   

    2007-04-06 19:17 by Jkallen
    寫得挺好的

    # re: JUnit源碼分析(四)——從Decorator模式說起  回復  更多評論   

    2009-09-10 17:15 by echozhjun
    看完四篇,很是受用。樓主辛苦了。

    # re: JUnit源碼分析(四)——從Decorator模式說起[未登錄]  回復  更多評論   

    2010-06-03 22:06 by richard
    以前看設計模式書中的裝飾模式,書中的例子好象是view和scrollview,看不出decorater 味道。看了你的文章之后又進一步的認識。
    主站蜘蛛池模板: 亚洲精华国产精华精华液好用| WWW免费视频在线观看播放| 日韩精品免费一区二区三区| 免费国产a理论片| 亚洲AV日韩AV天堂久久| 思思re热免费精品视频66| 日韩国产欧美亚洲v片| 亚洲人成人无码网www电影首页 | 色视频在线观看免费| 亚洲大尺度无码专区尤物| 免费毛片在线看片免费丝瓜视频| 日本视频免费观看| 亚洲图片中文字幕| 亚洲中文字幕无码久久2017| 91在线视频免费看| av永久免费网站在线观看| 亚洲私人无码综合久久网| 亚洲AV无码乱码在线观看裸奔| 成年人网站在线免费观看| 久久免费观看国产精品88av| 精品久久久久久亚洲综合网| 精品日韩亚洲AV无码一区二区三区 | 亚洲大成色www永久网址| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 亚洲AV中文无码乱人伦下载| 国产免费人视频在线观看免费| 一级毛片免费观看| 日本不卡视频免费| 免费在线看黄网站| 国产亚洲美女精品久久久久| 亚洲国产av一区二区三区丶| 中文亚洲AV片在线观看不卡| 日韩免费无砖专区2020狼| 又大又硬又爽又粗又快的视频免费| 国产乱子伦精品免费视频| 亚洲欧美日韩国产成人| 亚洲精品无码久久久久久久| 亚洲国产精品嫩草影院在线观看| 亚洲AV成人潮喷综合网| 久久最新免费视频| 美女露隐私全部免费直播|