## 問題 Problem
你需要準備一個復雜的、由多個部分組成的對象,但是你希望生成多次,或者使用不同的配置生成。
You need to prepare a complicated, multi-part object, but you expect to do it more than once or with varying configurations.
## 方法 Solution
創建一個“建造者”來分裝對象的創建過程。
Create a Builder to encapsulate the object production process.
[Todo.txt](http://todotxt.com/)格式提供了一種高級的(仍然是純文本)方法來管理todo列表。手動打出每一項很累也很容易出錯,因而一個TodoTxtBuilder類可以避免這些麻煩:
The?[Todo.txt](http://todotxt.com/)?format provides an advanced but still plain-text method for maintaining lists of to-do items. Typing out each item by hand would provide exhausting and error-prone, however, so a TodoTxtBuilder class could save us the trouble:
~~~
class TodoTxtBuilder
constructor: (defaultParameters={ }) ->
@date = new Date(defaultParameters.date) or new Date
@contexts = defaultParameters.contexts or [ ]
@projects = defaultParameters.projects or [ ]
@priority = defaultParameters.priority or undefined
newTodo: (description, parameters={ }) ->
date = (parameters.date and new Date(parameters.date)) or @date
contexts = @contexts.concat(parameters.contexts or [ ])
projects = @projects.concat(parameters.projects or [ ])
priorityLevel = parameters.priority or @priority
createdAt = [date.getFullYear(), date.getMonth()+1, date.getDate()].join("-")
contextNames = ("@#{context}" for context in contexts when context).join(" ")
projectNames = ("+#{project}" for project in projects when project).join(" ")
priority = if priorityLevel then "(#{priorityLevel})" else ""
todoParts = [priority, createdAt, description, contextNames, projectNames]
(part for part in todoParts when part.length > 0).join " "
builder = new TodoTxtBuilder(date: "10/13/2011")
builder.newTodo "Wash laundry"
# => '2011-10-13 Wash laundry'
workBuilder = new TodoTxtBuilder(date: "10/13/2011", contexts: ["work"])
workBuilder.newTodo "Show the new design pattern to Lucy", contexts: ["desk", "xpSession"]
# => '2011-10-13 Show the new design pattern to Lucy @work @desk @xpSession'
workBuilder.newTodo "Remind Sean about the failing unit tests", contexts: ["meeting"], projects: ["compilerRefactor"], priority: 'A'
# => '(A) 2011-10-13 Remind Sean about the failing unit tests @work @meeting +compilerRefactor'
~~~
## 討論 Discussion
TodoTxtBuilder包攬了所有繁重的生成文本的工作,使得程序員把注意力放在每個todo項不一樣的部分。而且,可以把命令行工具或者GUI插入到這段代碼中,and still retain support for later, more advanced versions of the format with ease.
The TodoTxtBuilder class takes care of all the heavy lifting of text generation and lets the programmer focus on the unique elements of each to-do item. Additionally, a command line tool or GUI could plug into this code and still retain support for later, more advanced versions of the format with ease.
### 開工前 Pre-Construction
無需每次都重新創建一個需要對象的實例,我們可以組建轉移到別的對象上,這樣我們可以在隨后的創建過程中擦改。 Instead of creating a new instance of the needed object from scratch every time, we shift the burden to a separate object that we can then tweak during the object creation process.
~~~
builder = new TodoTxtBuilder(date: "10/13/2011")
builder.newTodo "Order new netbook"
# => '2011-10-13 Order new netbook'
builder.projects.push "summerVacation"
builder.newTodo "Buy suntan lotion"
# => '2011-10-13 Buy suntan lotion +summerVacation'
builder.contexts.push "phone"
builder.newTodo "Order tickets"
# => '2011-10-13 Order tickets @phone +summerVacation'
delete builder.contexts[0]
builder.newTodo "Fill gas tank"
# => '2011-10-13 Fill gas tank +summerVacation'
~~~
### 練習 Exercises
* 補充project-和context-tag產生器的代碼,過濾掉重復的項;
* 有些Todo.txt的用戶常常會把project和context標記插入到todo項的描述中,添加一些代碼吧這些標識出這些記號,并把它們從后面的標記剔除掉。
* Expand the project- and context-tag generation code to filter out duplicate entries.
* Some Todo.txt users like to insert project and context tags inside the description of their to-do items. Add code to identify these tags and filter them out of the end tags.
- 貢獻
- 作者
- 授權協議
- 1、Syntax
- 在服務端和客戶端重用代碼
- For循環
- 嵌入JavaScript代碼
- 值域
- 2、Classes and Objects
- 類方法和實例方法
- CoffeeScript式的Type函數
- 鏈式調用
- 克隆對象(深度克隆)
- 不存在就賦值為對象字面量
- 類變量
- 3、Strings
- 分割字符串
- 字符串匹配
- 查找子字符串
- 讓整個字符串小寫
- 大寫整個字符
- 去掉字符串首尾的空白
- 生成唯一的ID
- 首字母大寫
- 重復字符串
- 字符串插值
- 4、Arrays
- Python式的Zip函數 Python-like Zip Function
- 數組去重 Removing Duplicate Elements from Arrays
- 基于數組構建字典對象 Creating a dictionary Object from an Array
- 數組轉成字符串 Creating a String from an Array
- 檢查每一個元素 Testing Every Element
- 數組最大值
- 過濾數組 Filtering Arrays
- 定義區間數組 Define Ranges Array
- 轉置數組 Reversing Arrays
- 化簡數組 Reducing Arrays
- 使用數組來做值交換 Using Arrays to Swap Variables
- 列表解析 List Comprehensions
- 檢查值的類型是否是數組
- 連接數組
- 攪亂數組中的元素 Shuffling Array Elements
- 數組映射 Mapping Arrays
- 5、Dates and Times
- Calculate Phase of the Moon for a Date
- 找出某月的最后一天是幾號 Finding the Last Day of the Month
- 獲取兩個日期相差的天數 Get Days Between Two Dates
- 計算復活節島日期 Calculate the Date of Easter Sunday
- 計算感恩節的日期(美國和加拿大) Calculate the Date of Thanksgiving (USA and Canada)
- 計算上一個(下一個)月份 Finding Last (or Next) Month
- 6、Math
- 快速逆平方根
- 一個隨機整數的函數
- 更快的斐波那契算法
- 生成可預測的隨機數
- 弧度與度轉換
- 生成隨機數
- 數學常數
- 7、Functions
- 反抖動函數 Debounce Functions
- 參數數組化 Splat Arguments
- 當函數調用的括號不可以省略時 When Function Parentheses Are Not Optional
- 遞歸函數 Recursive Functions
- 8、Metaprogramming
- 擴展內置對象 Extending Built-in Objects
- 檢測并創建缺失的函數 Detecting and Creating Missing Functions
- 9、jQuery
- 回調綁定
- 創建jQuery插件
- AJAX
- 10、Ajax
- 不依賴jQuery的Ajax請求 Ajax Request Without jQuery
- 11、Regular Expressions
- 替換子字符串 Replacing Substrings
- 使用定點 Using Heregexes
- 使用HTML字符實體替換HTML標簽 Replacing HTML Tags with HTML Named Entities
- 搜索子字符串 Searching for Substrings
- 12、Networking
- 簡單的服務器
- 雙向客戶端
- 最簡單的HTTP客戶端
- 最簡單的HTTP服務器
- 簡單的客戶端
- 雙向服務端 Bi-Directional Server
- 13、Design Patterns
- 命令模式
- 單例模式
- 策略模式 Strategy Pattern
- 建造者模式 Builder Pattern
- 備忘錄模式 Memento Pattern
- 解釋器模式 Interpreter Pattern
- 裝飾者模式
- 橋接模式
- 工廠方法模式
- 14、Databases
- MongoDB
- SQLite
- 15、Testing
- 使用Jasmine測試