Created
July 27, 2013 14:07
-
-
Save zaneli/6094975 to your computer and use it in GitHub Desktop.
「CoffeeScript によるデザインパターン(Composite)」ブログ用
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Task | |
constructor: (name, getTime) -> | |
@getName = -> name | |
@getTimeRequired = -> getTime() | |
@parent = null | |
class CompositeTask extends Task | |
constructor: (name) -> | |
super(name, => @subTasks.reduce ((sum, time) -> sum + time.getTimeRequired()), 0) | |
@subTasks = [] | |
addSubTask: (tasks...) -> | |
for task in tasks | |
if task?.getName? and task?.getTimeRequired? | |
task.parent = @ | |
@subTasks.push task | |
else | |
console.warn task?.constructor?.name + " is not a task" | |
@ | |
removeSubTask: (tasks...) -> | |
for task in tasks | |
index = @subTasks.indexOf(task) | |
if index >= 0 | |
@subTasks.splice(index, 1) | |
task.parent = null | |
@ | |
class @AddDryIngredientsTask extends Task | |
constructor: -> super("Add dry ingredients", -> 1.0) # 小麦粉と砂糖を加えるのに1分 | |
class @MixTask extends Task | |
constructor: -> super("Mix that batter up!", -> 3.0) # 混ぜるのに3分 | |
class @MakeBatterTask extends CompositeTask | |
constructor: -> | |
super("Make batter") | |
@addSubTask(new AddDryIngredientsTask(), new MixTask()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Task | |
constructor: (name, getTime) -> | |
@getName = -> name | |
@getTimeRequired = -> getTime() | |
class @AddDryIngredientsTask extends Task | |
constructor: -> super("Add dry ingredients", -> 1.0) # 小麦粉と砂糖を加えるのに1分 | |
class @MixTask extends Task | |
constructor: -> super("Mix that batter up!", -> 3.0) # 混ぜるのに3分 | |
class @MakeBatterTask extends Task | |
constructor: -> | |
super("Make batter", => @subTasks.reduce ((sum, time) -> sum + time.getTimeRequired()), 0) | |
@subTasks = [] | |
@addSubTask(new AddDryIngredientsTask(), new MixTask()) | |
addSubTask: (tasks...) -> | |
for task in tasks | |
if task?.getName? and task?.getTimeRequired? | |
@subTasks.push task | |
else | |
console.warn task?.constructor?.name + " is not a task" | |
@ | |
removeSubTask: (tasks...) -> | |
for task in tasks | |
index = @subTasks.indexOf(task) | |
@subTasks.splice(index, 1) if index >= 0 | |
@ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Task | |
constructor: (name, getTime) -> | |
@getName = -> name | |
@getTimeRequired = -> getTime() | |
class CompositeTask extends Task | |
constructor: (name) -> | |
super(name, => @subTasks.reduce ((sum, time) -> sum + time.getTimeRequired()), 0) | |
@subTasks = [] | |
addSubTask: (tasks...) -> | |
for task in tasks | |
if task?.getName? and task?.getTimeRequired? | |
@subTasks.push task | |
else | |
console.warn task?.constructor?.name + " is not a task" | |
@ | |
removeSubTask: (tasks...) -> | |
for task in tasks | |
index = @subTasks.indexOf(task) | |
@subTasks.splice(index, 1) if index >= 0 | |
@ | |
class @AddDryIngredientsTask extends Task | |
constructor: -> super("Add dry ingredients", -> 1.0) # 小麦粉と砂糖を加えるのに1分 | |
class @MixTask extends Task | |
constructor: -> super("Mix that batter up!", -> 3.0) # 混ぜるのに3分 | |
class @MakeBatterTask extends CompositeTask | |
constructor: -> | |
super("Make batter") | |
@addSubTask(new AddDryIngredientsTask(), new MixTask()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Task | |
constructor: (name, getTime) -> | |
@getName = -> name | |
@getTimeRequired = -> getTime() | |
class CompositeTask extends Array | |
constructor: (name) -> | |
@getName = -> name | |
@getTimeRequired = -> @reduce ((sum, time) -> sum + time.getTimeRequired()), 0 | |
class @AddDryIngredientsTask extends Task | |
constructor: -> super("Add dry ingredients", -> 1.0) # 小麦粉と砂糖を加えるのに1分 | |
class @MixTask extends Task | |
constructor: -> super("Mix that batter up!", -> 3.0) # 混ぜるのに3分 | |
class @MakeBatterTask extends CompositeTask | |
constructor: -> | |
super("Make batter") | |
@push(new AddDryIngredientsTask(), new MixTask()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package views | |
import org.specs2.mutable.Specification | |
import play.api.test.TestServer | |
import play.api.test.Helpers.{ running, HTMLUNIT } | |
class CompositeSpec extends Specification { | |
private val testPort = 3333 | |
"Composite" should { | |
"get time required" in { | |
running(TestServer(testPort), HTMLUNIT) { browser => | |
browser.goTo(s"http://localhost:${testPort}/composite") | |
browser.executeScript(""" | |
var adiTask = new AddDryIngredientsTask(); | |
console.log(adiTask.getTimeRequired()); | |
var mTask = new MixTask(); | |
console.log(mTask.getTimeRequired()); | |
var mbTask = new MakeBatterTask(); | |
console.log(mbTask.getTimeRequired()); | |
""") | |
browser.$("#__console_log").getValue must_== """1 | |
3 | |
4 | |
""" | |
browser.$("#__console_warn").getValue must beNull | |
} | |
} | |
"add some tasks" in { | |
running(TestServer(testPort), HTMLUNIT) { browser => | |
browser.goTo(s"http://localhost:${testPort}/composite") | |
browser.executeScript(""" | |
var task = new MakeBatterTask(); | |
console.log(task.getTimeRequired()); | |
task.addSubTask(new AddDryIngredientsTask()); | |
console.log(task.getTimeRequired()); | |
task.addSubTask(new AddDryIngredientsTask(), new MixTask()); | |
console.log(task.getTimeRequired()); | |
""") | |
browser.$("#__console_log").getValue must_== """4 | |
5 | |
9 | |
""" | |
browser.$("#__console_warn").getValue must beNull | |
} | |
} | |
"remove some tasks" in { | |
running(TestServer(testPort), HTMLUNIT) { browser => | |
browser.goTo(s"http://localhost:${testPort}/composite") | |
browser.executeScript(""" | |
var task = new MakeBatterTask(); | |
console.log(task.getTimeRequired()); | |
var task1 = new AddDryIngredientsTask(); | |
var task2 = new MixTask(); | |
var task3 = new AddDryIngredientsTask(); | |
var task4 = new MixTask(); | |
task.addSubTask(task1, task2, task3, task4); | |
console.log(task.getTimeRequired()); | |
task.removeSubTask(task1); | |
console.log(task.getTimeRequired()); | |
task.removeSubTask(task2, task3, task4); | |
console.log(task.getTimeRequired()); | |
""") | |
browser.$("#__console_log").getValue must_== """4 | |
12 | |
11 | |
4 | |
""" | |
browser.$("#__console_warn").getValue must beNull | |
} | |
} | |
"remove notadded tasks" in { | |
running(TestServer(testPort), HTMLUNIT) { browser => | |
browser.goTo(s"http://localhost:${testPort}/composite") | |
browser.executeScript(""" | |
var task = new MakeBatterTask(); | |
console.log(task.getTimeRequired()); | |
var task1 = new AddDryIngredientsTask(); | |
var task2 = new MixTask(); | |
var task3 = new AddDryIngredientsTask(); | |
var task4 = new MixTask(); | |
task.removeSubTask(task1); | |
console.log(task.getTimeRequired()); | |
task.removeSubTask(task2, task3, task4); | |
console.log(task.getTimeRequired()); | |
""") | |
browser.$("#__console_log").getValue must_== """4 | |
4 | |
4 | |
""" | |
browser.$("#__console_warn").getValue must beNull | |
} | |
} | |
"add invalid tasks" in { | |
running(TestServer(testPort), HTMLUNIT) { browser => | |
browser.goTo(s"http://localhost:${testPort}/composite") | |
browser.executeScript(""" | |
var task = new MakeBatterTask(); | |
console.log(task.getTimeRequired()); | |
task.addSubTask(1, "a", null); | |
console.log(task.getTimeRequired()); | |
""") | |
browser.$("#__console_log").getValue must_== """4 | |
4 | |
""" | |
browser.$("#__console_warn").getValue must_== """Number is not a task | |
String is not a task | |
undefined is not a task | |
""" | |
} | |
} | |
"remove invalid tasks" in { | |
running(TestServer(testPort), HTMLUNIT) { browser => | |
browser.goTo(s"http://localhost:${testPort}/composite") | |
browser.executeScript(""" | |
var task = new MakeBatterTask(); | |
console.log(task.getTimeRequired()); | |
task.removeSubTask(null, 10, "あ"); | |
console.log(task.getTimeRequired()); | |
""") | |
browser.$("#__console_log").getValue must_== """4 | |
4 | |
""" | |
browser.$("#__console_warn").getValue must beNull | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.console = | |
log: (msg) -> | |
idName = "__console_log" | |
$("body").append "<textarea id=\"#{idName}\">" if $("##{idName}").size() is 0 | |
$("##{idName}").val($("##{idName}").val() + "#{msg}\n") | |
warn: (msg) -> | |
idName = "__console_warn" | |
$("body").append "<textarea id=\"#{idName}\">" if $("##{idName}").size() is 0 | |
$("##{idName}").val($("##{idName}").val() + "#{msg}\n") | |
# テストケースで配列のindexOfが使用できなかったための回避コード | |
# 参考: http://qiita.com/Oakbow/items/3374175d76d82792134d | |
unless "indexOf" of Array:: | |
Array::indexOf = (find, i) -> | |
i = 0 if i is `undefined` | |
i += @length if i < 0 | |
i = 0 if i < 0 | |
n = @length | |
while i < n | |
return i if i of this and this[i] is find | |
i++ | |
-1 | |
# テストケースで配列のreduceが使用できなかったための回避コード | |
# 参考: http://d.hatena.ne.jp/gakuzo/20090414/1239681929 | |
unless "reduce" of Array:: | |
Array::reduce = (callback, init, thisObject) -> | |
return init if @length is 0 | |
index = (if init isnt `undefined` then 0 else 1) | |
result = (if init isnt `undefined` then init else this[0]) | |
n = @length | |
while index < n | |
result = callback.call(thisObject, result, this[index], index, this) | |
index++ | |
result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment