<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
    前面我們總結了Builder模式的構成、簡單的使用例子,現在我們來看Builder模式的一個完整例子,該例子模擬了一個后臺定時運行Job的構建過程:

    一、需求

    用戶可以創建一個定時運行的Job,該Job具有:任務Id,創建者,開始時間,結束時間,任務狀態。

    二、基本結構

    下面我們來看一張圖,從這張圖我們可以了解整個程序及Builder模式的構成




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

    1. Builder:包含了一個抽象的方法build

    2. JobBuilder:實現了Builder接口,在其build方法中實現了Job對象的構建。注意其中包含了Job對象所有屬性的一份拷貝,這是為了保存臨時緩存數據用的

    3. Job:定時任務類,包含了一個package access權限的構造方法和一系列get方法,要注意的是沒有set方法

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

    好,下面我們再來看一張圖,看看這些類之間到底是怎么合作的:




    可以看到JobParser類會在解析構建參數的過程中不斷調用JobBuilder類的set方法,將解析后的臨時數據保存到Builder的緩存變量中,而當解析完成后Builder就會從自身中取出所有的臨時數據,用來構建最終的目標對象。這個過程中最終構建的參數可能由于校驗而發生了變化(例如:對缺少變量的默認賦值)。

    三、代碼示例

    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接口是代表了一個生成器,它通過其build方法生成一個對象
     6 * 然后返回給調用者
     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來創建對象呢?下面是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參數的過程,在真實的環境中這個過程往往是
    16        // 通過GUI界面,由客戶輸入或選擇,在一步步的交互中完成。
    17
    18        // 此時Builder模式的好處就體現在它可以先將數據緩存在自己的內部,通過
    19        // 解析器(Parser)對用戶的輸入進行逐步的解析,這特別適合于需要通過大量
    20        // 的交互過程之后才能知道構建對象的所有最終屬性的情況(類似于Wizword)
    21
    22        // 這樣做的好處是確保到最后Builder模式構建出來的對象是可用的,有商業
    23        // 意義的。如果直接采用new一個對象的方法雖然簡單,但在構造過程非常復雜
    24        // 或長的情況下,除了會使目標類過于龐大之外,還可能出現當實例化一個對象
    25        // 后卻發現該對象由于某些屬性的問題而無效或沒有商業意義。
    26
    27        // 采用了Builder模式之后由于有了一個緩存和解析的過程,可以在解析的過程
    28        // 中規避各種錯誤,可以拋出異常。這樣就不會出現實例化了無用的對象而浪費
    29        // 內存的缺點了。而且可以使目標類集中于各種業務操作不用關心對象的實例化
    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


    總結:

    1. 使用Builder的最佳場合:

    使用Builder模式的最佳場合應該是:

    對象的構建過程長或復雜、構建對象所需的全部參數無法在一開始就完全獲得,必須通過一步步的交互過程來獲取。例如:通過Web頁面的輸入或用戶選擇來構建所需對象

    2. Builder模式的好處:

    Builder模式的一個最重要的好處除了將對象構建的“部件”和“過程”解耦之外,還能夠保證我們構建出來的對象都是完整的,可用的,具有商業意義的。如果因為構建參數的缺少或錯誤而導致直接實例化一個對象后才發現對象是不可用的,會浪費系統的資源,使用Builder模式則可用避免這種情況。

    附:BuilderPattern的源代碼


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


    FeedBack:
    # re: 設計模式總結-Builder模式(二)
    2008-01-03 10:53 | TonySoft
    兄弟,你的UML圖是用什么工具畫的?  回復  更多評論
      
    # re: 設計模式總結-Builder模式(二)
    2008-01-03 13:18 | Paul Lin
    用Eclipse的UML插件eUML2自動生成的。

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

    常用鏈接

    留言簿(21)

    隨筆分類

    隨筆檔案

    BlogJava熱點博客

    好友博客

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产免费69成人精品视频 | 亚洲国产成人久久精品动漫| 亚洲三级在线视频| 无码人妻精品中文字幕免费| 亚洲精品无码MV在线观看| kk4kk免费视频毛片| 中文字幕精品无码亚洲字| 一区二区三区视频免费| 亚洲国产人成中文幕一级二级| 黄页网址在线免费观看| 亚洲第一区精品日韩在线播放| 男女猛烈无遮掩视频免费软件| 亚洲欧洲精品成人久久曰影片| 久久国产一片免费观看| 久久久久久久久亚洲| **一级一级毛片免费观看| 亚洲网站在线免费观看| 亚洲w码欧洲s码免费| 亚洲欧美日韩国产精品一区| 在线播放高清国语自产拍免费| 最新亚洲人成网站在线观看| 亚洲精品无码久久久| 国产啪精品视频网站免费尤物| 99久久亚洲综合精品成人网| 一二三四影视在线看片免费 | 日本中文一区二区三区亚洲| 亚洲AV无码一区二区三区性色 | 国产免费MV大全视频网站| 亚洲国产第一站精品蜜芽| 国产成人福利免费视频| 日日摸日日碰夜夜爽亚洲| 亚洲色成人WWW永久网站| 2020久久精品国产免费| 美女黄频视频大全免费的| 亚洲大尺度无码专区尤物| 免费av欧美国产在钱| eeuss影院免费直达入口| 亚洲国产精品成人精品软件| 成人免费视频国产| 可以免费观看的国产视频| 亚洲熟女精品中文字幕|