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

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

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

    posts - 262,  comments - 221,  trackbacks - 0
    前面我們總結(jié)了Builder模式的構(gòu)成、簡(jiǎn)單的使用例子,現(xiàn)在我們來(lái)看Builder模式的一個(gè)完整例子,該例子模擬了一個(gè)后臺(tái)定時(shí)運(yùn)行Job的構(gòu)建過(guò)程:

    一、需求

    用戶可以創(chuàng)建一個(gè)定時(shí)運(yùn)行的Job,該Job具有:任務(wù)Id,創(chuàng)建者,開(kāi)始時(shí)間,結(jié)束時(shí)間,任務(wù)狀態(tài)。

    二、基本結(jié)構(gòu)

    下面我們來(lái)看一張圖,從這張圖我們可以了解整個(gè)程序及Builder模式的構(gòu)成




    我們可以看到在這個(gè)包圖中,有4個(gè)比較重要的類(lèi)、接口:

    1. Builder:包含了一個(gè)抽象的方法build

    2. JobBuilder:實(shí)現(xiàn)了Builder接口,在其build方法中實(shí)現(xiàn)了Job對(duì)象的構(gòu)建。注意其中包含了Job對(duì)象所有屬性的一份拷貝,這是為了保存臨時(shí)緩存數(shù)據(jù)用的

    3. Job:定時(shí)任務(wù)類(lèi),包含了一個(gè)package access權(quán)限的構(gòu)造方法和一系列g(shù)et方法,要注意的是沒(méi)有set方法

    4.JobParser:Job解析器,用于解析用戶從GUI界面輸入的各種文本參數(shù)

    好,下面我們?cè)賮?lái)看一張圖,看看這些類(lèi)之間到底是怎么合作的:




    可以看到JobParser類(lèi)會(huì)在解析構(gòu)建參數(shù)的過(guò)程中不斷調(diào)用JobBuilder類(lèi)的set方法,將解析后的臨時(shí)數(shù)據(jù)保存到Builder的緩存變量中,而當(dāng)解析完成后Builder就會(huì)從自身中取出所有的臨時(shí)數(shù)據(jù),用來(lái)構(gòu)建最終的目標(biāo)對(duì)象。這個(gè)過(guò)程中最終構(gòu)建的參數(shù)可能由于校驗(yàn)而發(fā)生了變化(例如:對(duì)缺少變量的默認(rèn)賦值)。

    三、代碼示例

    1. Job

     1/**
     2     * Instantiates a new job.
     3     * 
     4     * @param id the id
     5     * @param description the description
     6     * @param owner the owner
     7     * @param start the start
     8     * @param end the end
     9     * @param status the status
    10     */

    11    Job(long id, String description, String owner, Date start, Date end,
    12            String status) {
    13        this.jobId = id;
    14        this.jobDescription = description;
    15        this.jobOwner = owner;
    16        this.jobStartTime = start;
    17        this.jobEndTime = end;
    18        this.jobStatus = status;
    19    }

    20


    2. Builder

     1package org.pattern.build;
     2
     3/**
     4 * <pre>
     5 * Builder接口是代表了一個(gè)生成器,它通過(guò)其build方法生成一個(gè)對(duì)象
     6 * 然后返回給調(diào)用者
     7 * </pre>
     8 * 
     9 * @author Paul Lin
    10 * @version 1.0
    11 * @uml.dependency   supplier="org.pattern.build.BuilderException"
    12 */

    13public interface Builder {
    14
    15    /**
    16     * Builds the destination object. The implement class
    17     * should be return an Object that represent the fianl
    18     * object
    19     * 
    20     * @return the object
    21     * 
    22     * @throws BuilderException the builder exception
    23     */

    24    public Object build() throws BuilderException;
    25}


    3. JobBuilder

     1public Job build() throws BuilderException{
     2        boolean valid = true;
     3        String errorReason = "";
     4        if (jobId <= 0{
     5            valid = false;
     6            errorReason = " Id should be large than 0.";
     7        }

     8        if (jobOwner == null || (jobOwner.trim().length() == 0)) {
     9            valid = false;
    10            errorReason = " Job owner shoud not be null.";
    11        }

    12        if (jobStartTime == null{
    13            valid = false;
    14            errorReason = " Job start time shoud not be null.";
    15        }

    16        if ((jobStartTime.getTime() - jobEndTime.getTime()) > 0{
    17            valid = false;
    18            errorReason = " Job start time should be less or equals than end time.";
    19        }

    20        if (!jobStatus.equalsIgnoreCase("NA")) {
    21            valid = false;
    22            errorReason = " Job status shoud be 'NA' at first.";
    23        }

    24        if (valid) {
    25            return new Job(jobId, jobDescription, jobOwner, jobStartTime,
    26                    jobEndTime, jobStatus);
    27        }
     else {
    28            throw new BuilderException(errorReason);
    29        }

    30    }


    4. JobParser

     1/**
     2     * Parses the HashMap object to extract
     3     * all kinds of imormation about a job.
     4     * May use "default value" when exception
     5     * happened. 
     6     * 
     7     * @param map the map
     8     */

     9    public void parse(HashMap map) {
    10        if (map != null{
    11            for (Iterator it = map.keySet().iterator(); it.hasNext();) {
    12                String key = (String) it.next();
    13                String value = (String) map.get(key);
    14                // Parse key/value pair
    15                if (key.equalsIgnoreCase("id")) {
    16                    builder.setJobId(new Long(value).longValue());
    17                }
     else if (key.equalsIgnoreCase("description")) {
    18                    builder.setJobDescription(value);
    19                }
     else if (key.equalsIgnoreCase("owner")) {
    20                    builder.setJobOwner(value);
    21                }
     else if (key.equalsIgnoreCase("start")) {
    22                    SimpleDateFormat sdf = new SimpleDateFormat(
    23                            "yyyy-MM-dd HH:mm:ss");
    24                    try {
    25                        builder.setJobStartTime(sdf.parse(value));
    26                    }
     catch (ParseException pe) {
    27                        builder.setJobStartTime(new Date());
    28                    }

    29
    30                }
     else if (key.equalsIgnoreCase("end")) {
    31                    SimpleDateFormat sdf = new SimpleDateFormat(
    32                            "yyyy-MM-dd HH:mm:ss");
    33                    try {
    34                        builder.setJobEndTime(sdf.parse(value));
    35                    }
     catch (ParseException pe) {
    36                        builder.setJobEndTime(null);
    37                    }

    38
    39                }
     else if (key.equalsIgnoreCase("status")) {
    40                    builder.setJobStatus(value);
    41                }
     else {
    42                    // Do nothing
    43                }

    44            }

    45        }

    46    }

    那么如何使用Builder和Parser來(lái)創(chuàng)建對(duì)象呢?下面是JobBuilderTest的示例代碼

     1package org.pattern.build;
     2
     3import java.util.HashMap;
     4
     5public class JobBuilerTest {
     6
     7    public static void main(String args[]) {
     8        new JobBuilerTest().testJobBuilder();
     9    }

    10
    11    /**
    12     * Test job builder.
    13     */

    14    public void testJobBuilder() {
    15        // 此處省略了從客戶端獲取Job參數(shù)的過(guò)程,在真實(shí)的環(huán)境中這個(gè)過(guò)程往往是
    16        // 通過(guò)GUI界面,由客戶輸入或選擇,在一步步的交互中完成。
    17
    18        // 此時(shí)Builder模式的好處就體現(xiàn)在它可以先將數(shù)據(jù)緩存在自己的內(nèi)部,通過(guò)
    19        // 解析器(Parser)對(duì)用戶的輸入進(jìn)行逐步的解析,這特別適合于需要通過(guò)大量
    20        // 的交互過(guò)程之后才能知道構(gòu)建對(duì)象的所有最終屬性的情況(類(lèi)似于Wizword)
    21
    22        // 這樣做的好處是確保到最后Builder模式構(gòu)建出來(lái)的對(duì)象是可用的,有商業(yè)
    23        // 意義的。如果直接采用new一個(gè)對(duì)象的方法雖然簡(jiǎn)單,但在構(gòu)造過(guò)程非常復(fù)雜
    24        // 或長(zhǎng)的情況下,除了會(huì)使目標(biāo)類(lèi)過(guò)于龐大之外,還可能出現(xiàn)當(dāng)實(shí)例化一個(gè)對(duì)象
    25        // 后卻發(fā)現(xiàn)該對(duì)象由于某些屬性的問(wèn)題而無(wú)效或沒(méi)有商業(yè)意義。
    26
    27        // 采用了Builder模式之后由于有了一個(gè)緩存和解析的過(guò)程,可以在解析的過(guò)程
    28        // 中規(guī)避各種錯(cuò)誤,可以拋出異常。這樣就不會(huì)出現(xiàn)實(shí)例化了無(wú)用的對(duì)象而浪費(fèi)
    29        // 內(nèi)存的缺點(diǎn)了。而且可以使目標(biāo)類(lèi)集中于各種業(yè)務(wù)操作不用關(guān)心對(duì)象的實(shí)例化
    30        HashMap<String, String> map = new HashMap<String, String>();
    31        map.put("id""1");
    32        map.put("description""job for test");
    33        map.put("owner""paul");
    34        map.put("start""2007-12-26 12:00:00");
    35        map.put("end""2007-12-26 23:59:59");
    36        map.put("status""NA");
    37
    38        // Create a builder
    39        Builder builder = new JobBuilder();
    40        // Create a parser with the builder as it's parameter
    41        JobParser parser = new JobParser(builder);
    42        // Parse the job data
    43        parser.parse(map);
    44        // Return the job
    45        try {
    46            Job job = (Job) builder.build();
    47            System.out.println(job.toString());
    48        }
     catch (BuilderException be) {
    49            // TODO Auto-generated catch block
    50            be.printStackTrace();
    51        }

    52    }

    53
    54}

    55


    總結(jié):

    1. 使用Builder的最佳場(chǎng)合:

    使用Builder模式的最佳場(chǎng)合應(yīng)該是:

    對(duì)象的構(gòu)建過(guò)程長(zhǎng)或復(fù)雜、構(gòu)建對(duì)象所需的全部參數(shù)無(wú)法在一開(kāi)始就完全獲得,必須通過(guò)一步步的交互過(guò)程來(lái)獲取。例如:通過(guò)Web頁(yè)面的輸入或用戶選擇來(lái)構(gòu)建所需對(duì)象

    2. Builder模式的好處:

    Builder模式的一個(gè)最重要的好處除了將對(duì)象構(gòu)建的“部件”和“過(guò)程”解耦之外,還能夠保證我們構(gòu)建出來(lái)的對(duì)象都是完整的,可用的,具有商業(yè)意義的。如果因?yàn)闃?gòu)建參數(shù)的缺少或錯(cuò)誤而導(dǎo)致直接實(shí)例化一個(gè)對(duì)象后才發(fā)現(xiàn)對(duì)象是不可用的,會(huì)浪費(fèi)系統(tǒng)的資源,使用Builder模式則可用避免這種情況。

    附:BuilderPattern的源代碼


    -------------------------------------------------------------
    生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
    posted on 2008-01-02 23:51 Paul Lin 閱讀(1621) 評(píng)論(2)  編輯  收藏 所屬分類(lèi): 模式與重構(gòu)


    FeedBack:
    # re: 設(shè)計(jì)模式總結(jié)-Builder模式(二)
    2008-01-03 10:53 | TonySoft
    兄弟,你的UML圖是用什么工具畫(huà)的?  回復(fù)  更多評(píng)論
      
    # re: 設(shè)計(jì)模式總結(jié)-Builder模式(二)
    2008-01-03 13:18 | Paul Lin
    用Eclipse的UML插件eUML2自動(dòng)生成的。

    下載地址:http://www.soyatec.cn/euml2/  回復(fù)  更多評(píng)論
      
    <2008年1月>
    303112345
    6789101112
    13141516171819
    20212223242526
    272829303112
    3456789

    常用鏈接

    留言簿(21)

    隨筆分類(lèi)

    隨筆檔案

    BlogJava熱點(diǎn)博客

    好友博客

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲精品国产精品乱码不卡√| 亚洲高清视频一视频二视频三| 女人张腿给男人桶视频免费版 | 国产偷国产偷亚洲高清在线| 免费a在线观看播放| 免费一级毛片正在播放| 国产亚洲av片在线观看播放 | 亚洲色精品vr一区二区三区| 亚洲av福利无码无一区二区| 亚洲熟妇无码AV在线播放| 亚洲最大成人网色| 亚洲日韩精品国产一区二区三区 | 理论亚洲区美一区二区三区| 国产日韩精品无码区免费专区国产| 日韩精品极品视频在线观看免费| 国色精品卡一卡2卡3卡4卡免费| 四虎永久免费地址在线网站| 亚洲国产精彩中文乱码AV| 亚洲av无码片在线观看| 日韩大片在线永久免费观看网站| 久久大香香蕉国产免费网站| 成人免费看黄20分钟| 伊人久久大香线蕉亚洲五月天| 亚洲伊人久久大香线蕉啊| 猫咪免费人成在线网站| 99久热只有精品视频免费观看17| 日本成人免费在线| 亚洲国产女人aaa毛片在线| 亚洲国产无线乱码在线观看| 在线观看肉片AV网站免费| 女人被男人桶得好爽免费视频| 亚洲日本乱码在线观看| 亚洲日本VA午夜在线电影| 在线观看片免费人成视频播放| 毛色毛片免费观看| 国产l精品国产亚洲区在线观看| 亚洲欧洲无码AV不卡在线| 国内精品免费视频精选在线观看| 永久免费视频v片www| 亚洲成在人天堂一区二区| 色婷婷亚洲一区二区三区|