オブジェクト指向プログラミングでFizzBuzz

オブジェクト指向プログラミングは、オブジェクトが連携して動くとかオブジェクトがメッセージを送りあって動くとか言われるが、オブジェクト指向プログラミングはどういうものかを説明するときは、その準備をするところも含めて語らないといけない気がする。
1. 適切な粒度の部品ごとにオブジェクトを定義する。
2. 複合オブジェクトの組み立て(オブジェクトと通信先のオブジェクトの関連性を登録する)。
3. 代表であるオブジェクトのメソッドを呼び出す(オブジェクトに操作メッセージを送る)。
というのが正しい説明じゃないだろうか。
そういう考えでCoffeeScriptFizzBuzzを作ってみた。

main = ->
	out = new Outputer
	fb = new FbGame(new Counter, out)
	fb.addRule new FbRuleHitToSay("FizzBuzz", (n) -> n % 3 == 0 && n % 5 == 0)
	fb.addRule new FbRuleHitToSay("Fizz"    , (n) -> n % 3 == 0)
	fb.addRule new FbRuleHitToSay("Buzz"    , (n) -> n % 5 == 0)
	fb.addRule new FbRuleNum()

	fb.run()
	out.flush()

class FbGame
	constructor: (@cnt, @out) ->
		@rules=[]
	addRule: (rule) ->
		@rules.push rule
	run: ->
		for n in @cnt.getList()
			@out.print @conv(n)
	conv: (n) ->
		for rule in @rules
			return rule.getStr(n) if rule.isHit(n)

class Counter
	getList: -> [1..100]

class Outputer
	constructor: ->
		@out = []
	print: (s) -> @out.push s
	flush: -> console.log @out.join(",")

class FbRuleBase
	constructor: ->
	isHit: (n) ->
	getStr: (n) ->

class FbRuleHitToSay extends FbRuleBase
	constructor: (@sayStr, @isHitFunc) ->
	isHit: (n) -> @isHitFunc n
	getStr: (n) -> @sayStr

class FbRuleNum extends FbRuleBase
	isHit: (n) -> true
	getStr: (n) -> n