Skip to content

Instantly share code, notes, and snippets.

@zerobase
Created November 21, 2013 12:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zerobase/7580821 to your computer and use it in GitHub Desktop.
Save zerobase/7580821 to your computer and use it in GitHub Desktop.
CoffeeScript vs Literate CoffeeScript ref: http://qiita.com/zerobase/items/86cc00bd14d901274c32
###
# Factory Method Example in CoffeeScript
## Introduction
This example of the factory method pattern is a part of a [Tic-tac-toe](http://en.wikipedia.org/wiki/Tic-tac-toe) application. See [Wikipedia](http://en.wikipedia.org/wiki/File:Factory_Method_UML_class_diagram.svg) for the UML diagram of the factory method pattern.
This example has four classes: Grid, GridCell, Board and Space.
Grid and GridCell are general purpose classes. Suppose they are provided by an external library.
Grid (Creator) doesn't know Space (ConcreteProduct) because Grid is an external library class:
###
class Grid # <<Creator>>
@cells = []
@row = 0
@column = 0
constructor: (@rows, @columns) ->
size = @rows * @columns
@cells = new Array(size)
for row in [0...@rows]
for column in [0...@columns]
cell = this.newGridCell(row, column)
this.cellAt row, column, cell
newGridCell: () -> # returns GridCell
throw "abstract method"
cellAt: (row, column, val = null) ->
i = (row * @columns) + column
if val == null
@cells[i]
else
@cells[i] = val
cells: () ->
@cells
eachCellsInRow: (row, callback) ->
for column in [0...@columns]
callback this.cellAt(row, column)
eachCellsInColumn: (column, callback) ->
for row in [0...@rows]
callback this.cellAt(row, column)
each: (callback) ->
callback cell, index for index, cell of @cells
# GridCell is an abstract grid cell, used by Grid. GridCell (Product) doesn't know Board (ConcreteCreator) because GridCell is an external library class:
class GridCell # <<Product>>
constructor: (@row, @column) ->
# Board is a subclass of Grid. It overrides `#newGridCell` factory method:
class Board extends Grid # <<ConcreteCreator>>
constructor: (@rows, @columns) ->
super @rows, @columns
newGridCell: (row, column) ->
new Space(row, column)
# Space is a concrete GridCell, used by Board:
class Space extends GridCell # <<ConcreteProduct>>
constructor: (@row, @column) ->
@type = "Space"
# Here is an example:
board = new Board(3, 3)
#board.each (cell, index) ->
# console.log cell
console.log 'each cells in row 1:'
board.eachCellsInRow 1,
(cell, index) -> console.log cell
console.log 'each cells in columns 1:'
board.eachCellsInColumn 1,
(cell, index) -> console.log cell
###
# Result
$ coffee FactoryMethod.litcoffee
each cells in row 1:
{ row: 1, column: 0, type: 'Space' }
{ row: 1, column: 1, type: 'Space' }
{ row: 1, column: 2, type: 'Space' }
each cells in columns 1:
{ row: 0, column: 1, type: 'Space' }
{ row: 1, column: 1, type: 'Space' }
{ row: 2, column: 1, type: 'Space' }
###

Factory Method Example in CoffeeScript

Introduction

This example of the factory method pattern is a part of a Tic-tac-toe application. See Wikipedia for the UML diagram of the factory method pattern.

This example has four classes: Grid, GridCell, Board and Space.

Grid and GridCell are general purpose classes. Suppose they are provided by an external library.

Code

Grid (Creator) doesn't know Space (ConcreteProduct) because Grid is an external library class:

class Grid # <<Creator>>

  @cells = []
  @row = 0
  @column = 0

  constructor: (@rows, @columns) ->
    size = @rows * @columns
    @cells = new Array(size)
    for row in [0...@rows]
      for column in [0...@columns]
        cell = this.newGridCell(row, column)
        this.cellAt row, column, cell

  newGridCell: () -> # returns GridCell
    throw "abstract method"

  cellAt: (row, column, val = null) ->
    i = (row * @columns) + column
    if val == null
      @cells[i]
    else
      @cells[i] = val

  cells: () ->
    @cells

  eachCellsInRow: (row, callback) ->
    for column in [0...@columns]
      callback this.cellAt(row, column)

  eachCellsInColumn: (column, callback) ->
    for row in [0...@rows]
      callback this.cellAt(row, column)

  each: (callback) ->
    callback cell, index for index, cell of @cells

GridCell is an abstract grid cell, used by Grid. GridCell (Product) doesn't know Board (ConcreteCreator) because GridCell is an external library class:

class GridCell # <<Product>>

  constructor: (@row, @column) ->

Board is a subclass of Grid. It overrides #newGridCell factory method:

class Board extends Grid # <<ConcreteCreator>>

  constructor: (@rows, @columns) ->
    super @rows, @columns

  newGridCell: (row, column) ->
    new Space(row, column)

Space is a concrete GridCell, used by Board:

class Space extends GridCell # <<ConcreteProduct>>
  constructor: (@row, @column) ->
    @type = "Space"

Here is an example:

board = new Board(3, 3)

#board.each (cell, index) ->
#  console.log cell

console.log 'each cells in row 1:'
board.eachCellsInRow 1,
  (cell, index) -> console.log cell

console.log 'each cells in columns 1:'
board.eachCellsInColumn 1,
  (cell, index) -> console.log cell

This is a result:

###
$ coffee FactoryMethod.litcoffee
each cells in row 1:
{ row: 1, column: 0, type: 'Space' }
{ row: 1, column: 1, type: 'Space' }
{ row: 1, column: 2, type: 'Space' }
each cells in columns 1:
{ row: 0, column: 1, type: 'Space' }
{ row: 1, column: 1, type: 'Space' }
{ row: 2, column: 1, type: 'Space' }
###
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment