Ports of Gang of Four design patterns in coffee.
* Unfinished pattern
class AbstractProductA
constructor: (arg) ->
console.log arg
class AbstractProductB
constructor: (arg) ->
console.log arg
class ConcreteProductA1 extends AbstractProductA
class ConcreteProductA2 extends AbstractProductA
class ConcreteProductB1 extends AbstractProductB
class ConcreteProductB2 extends AbstractProductB
class AbstractFactory
createProductA: ->
createProductB: ->
class ConcreteFactory1 extends AbstractFactory
createProductA: ->
new ConcreteProductA1 'ConcreteProductA1'
createProductB: ->
new ConcreteProductB1 'ConcreteProductB1'
class ConcreteFactory2 extends AbstractFactory
createProductA: ->
new ConcreteProductA2 'ConcreteProductA2'
createProductB: ->
new ConcreteProductB2 'ConcreteProductB2'
class Client
constructor: (factory) ->
@abstractProductA = factory.createProductA()
@abstractProductB = factory.createProductB()
class Example
@run: ->
factory1 = new ConcreteFactory1()
client1 = new Client factory1
factory2 = new ConcreteFactory2()
client2 = new Client factory2
Example.run()
class Director
constructor: (@builder) ->
construct: (structure) ->
for obj in structure
console.log obj
@builder.buildPart obj
return
class Product
constructor: ->
@result = ''
append: (obj) ->
@result += obj
get: ->
@result
class Builder
buildPart: ->
class ConcreteBuilder extends Builder
constructor: ->
@product = new Product()
buildPart: (obj) ->
@product.append obj.toUpperCase()
getResult: ->
@product
class Client
@run: ->
concreteBuilder = new ConcreteBuilder()
director = new Director concreteBuilder
director.construct 'ohai'
result = concreteBuilder.getResult()
alert result.get()
Client.run()
class Product
class ConcreteProduct1 extends Product
class ConcreteProduct2 extends Product
class Creator
factoryMethod: ->
operation: ->
product = @factoryMethod()
class ConcreteCreator extends Creator
factoryMethod: (id) ->
switch id
when id is 1 then return new ConcreteProduct1()
when id is 2 then return new ConcreteProduct2()
class Example
@run: ->
creator = new ConcreteCreator()
console.log creator.factoryMethod 1
console.log creator.factoryMethod 2
console.log creator.factoryMethod 3
Example.run()
class Client
constructor: ->
operation: (prototype) ->
p = prototype.clone()
class Prototype
clone: ->
if Object.create
Object.create @
else # if < IE9
Clone = ->
Clone:: = @
new Clone()
setProperty: (@property) ->
logProperty: -> console.log @property or '-'
class ConcretePrototype1 extends Prototype
class ConcretePrototype2 extends Prototype
class Example
@run: ->
client = new Client()
cp1 = new ConcretePrototype1()
cp1Prototype = client.operation cp1
cp1.setProperty 'original1'
cp1Prototype.setProperty 'clone1'
cp1.logProperty()
cp1Prototype.logProperty()
Example.run()
class Singleton
@_instance: null
@getInstance: ->
@_instance ||= new @ arguments...
class Example
@run: ->
class ExampleClass extends Singleton
constructor: ->
properties: {}
set: (key, val) ->
@properties[key] = val
return
get: (key) ->
@properties[key]
example = ExampleClass.getInstance()
example.set 'Singleton', 'This is a singleton value'
console.log example.get 'Singleton'
Example.run()
class Target
request: ->
console.log 'Not fired'
class Adaptee
specificRequest: ->
console.log 'Specific request'
class Adapter extends Target
constructor: (@adaptee) ->
request: ->
@adaptee.specificRequest()
class Client
@run: ->
adaptee = new Adaptee()
adapter = new Adapter adaptee
adapter.request()
Client.run()
class Abstraction
constructor: (@imp) ->
operation: ->
@imp.operationImp()
class RefinedAbstraction extends Abstraction
class Implementor
operationImp: ->
class ConcreteImplementorA extends Implementor
operationImp: ->
console.log 'ConcreteImplementorA::operationImp'
class ConcreteImplementorB extends Implementor
operationImp: ->
console.log 'ConcreteImplementorB::operationImp'
class Client
@run: ->
concreteImplementorA = new ConcreteImplementorA()
refinedAbstractionA = new RefinedAbstraction concreteImplementorA
refinedAbstractionA.operation()
concreteImplementorB = new ConcreteImplementorB()
refinedAbstractionB = new RefinedAbstraction concreteImplementorB
refinedAbstractionB.operation()
Client.run()
class Component
constructor: ->
@list = []
getComposite: ->
operation: ->
add: (component) ->
class Leaf extends Component
class Composite extends Component
add: (component) ->
@list.push component
operation: ->
console.log @list
getComposite: ->
@
class Client
@run: ->
# Create a Composite object and add a Leaf
composite = new Composite()
leaf = new Leaf()
composite.add leaf
composite.operation()
# Add a Composite to the Composite
composite2 = new Composite()
composite.add composite2
composite.operation()
Client.run()
class Component
props: {}
add: (key, val) ->
@props[key] = val
get: ->
@props
process: ->
class ConcreteComponent extends Component
process: ->
class Decorator extends Component
constructor: (@component) ->
process: ->
@component.process()
class ConcreteDecoratorA extends Decorator
process: ->
@component.add 'concreteDecoratorAProcess', true
super()
class ConcreteDecoratorB extends Decorator
process: ->
@component.add 'concreteDecoratorBProcess', true
super()
class Example
@run: ->
cmpt = new ConcreteDecoratorA new ConcreteDecoratorB new ConcreteComponent()
cmpt.process()
Example.run()
class Subsystem1
constructor: ->
console.log 'subsystem1'
class Subsystem2
constructor: ->
console.log 'subsystem2'
class Facade
request: ->
s1 = new Subsystem1()
s2 = new Subsystem2()
class Client
@run: ->
facade = new Facade()
facade.request()
Client.run()
class FlyweightFactory
constructor: ->
@flyweights = {}
getFlyweight: (key) ->
unless @flyweights[key]?
@flyweights[key] = new ConcreteFlyweight key
@flyweights[key]
class Flyweight
constructor: (@key) ->
operation: (extrinsicState) ->
class ConcreteFlyweight extends Flyweight
intrinsicState: ''
operation: (extrinsicState) ->
@intrinsicState += "#{extrinsicState} "
console.log @intrinsicState
class UnsharedConcreteFlyweight extends Flyweight
allState: null
class Client
@run: ->
factory = new FlyweightFactory()
foo = factory.getFlyweight 'foo'
bar = factory.getFlyweight 'bar'
baz = factory.getFlyweight 'baz'
qux = factory.getFlyweight 'foo'
foo.operation 'red'
bar.operation 'green'
baz.operation 'blue'
qux.operation 'black'
Client.run()
class Subject
request: ->
class RealSubject extends Subject
request: ->
console.log 'Real subject'
class Proxy extends Subject
request: ->
unless @realSubject?
@realSubject = new RealSubject()
@realSubject.request()
class Client
@run: ->
proxy = new Proxy()
proxy.request()
Client.run()
class Handler
constructor: (@kind, @successor) ->
handleRequest: ->
if @successor
@successor.handleRequest()
class ConcreteHandler1 extends Handler
handleRequest: ->
console.log "#{@kind} handled"
class ConcreteHandler2 extends Handler
class Client
@run: ->
concreteHandler1 = new ConcreteHandler1 'foo'
concreteHandler2 = new ConcreteHandler2 'bar', concreteHandler1
concreteHandler2.handleRequest()
Client.run()
class Command
execute: ->
class Invoker
execute: (command) ->
command.execute()
class Receiver
action1: -> console.log 'action1'
action2: -> console.log 'action2'
class ConcreteCommandA extends Command
constructor: (@receiver) ->
execute: ->
@receiver.action1()
class ConcreteCommandB extends Command
constructor: (@receiver) ->
execute: ->
@receiver.action2()
class Client
@run: (action) ->
receiver = new Receiver()
ccmdA = new ConcreteCommandA receiver
ccmdB = new ConcreteCommandB receiver
invoker = new Invoker()
invoker.execute ccmdA if action is 1
invoker.execute ccmdB if action is 2
class Example
@run: ->
Client.run 1
Client.run 2
Example.run()
class Context
constructor: (@name) ->
getName: ->
@name
class AbstractExpression
constructor: ->
@expressions = []
interpret: (@context) ->
class TerminalExpression extends AbstractExpression
interpret: (@context) ->
console.log "Terminal expression for #{@context.getName()}"
class NonterminalExpression extends AbstractExpression
addExpression: (expression) ->
@expressions.push expression
interpret: (@context) ->
console.log "Nonterminal expression for #{@context.getName()}"
for expression in @expressions
expression.interpret @context
class Client
@run: ->
context = new Context '*le context'
root = new NonterminalExpression()
root.addExpression new TerminalExpression()
root.addExpression new TerminalExpression()
root.interpret context
Client.run()
class Iterator
first: ->
next: ->
isDone: ->
currentItem: ->
class ConcreteIterator extends Iterator
constructor: (@list) ->
@current = 0
first: ->
@current = 0
next: ->
@current += 1
isDone: ->
@current >= @list.count()
currentItem: ->
throw new Error 'IteratorOutOfBounds' if @isDone()
@list.get @current
class Aggregate
createIterator: ->
class ConcreteAggregate extends Aggregate
createIterator: (items) ->
list = new List()
for key, val of items
val.__POINTER__ = key
list.append val
new ConcreteIterator list
class Client
@run: ->
aggregate = new ConcreteAggregate()
iterator = aggregate.createIterator items
while not iterator.isDone()
current = iterator.currentItem()
# Do something with the item here...
iterator.next()
Client.run()
class Colleague
constructor: (@mediator) ->
changed: ->
@mediator.colleagueChanged @
class ConcreteColleague1 extends Colleague
event: ->
@changed()
class ConcreteColleague2 extends Colleague
event: ->
@changed()
class Mediator
colleagueChanged: (colleague) ->
class ConcreteMediator extends Mediator
createColleagues: ->
@colleague1 = new ConcreteColleague1 @
@colleague2 = new ConcreteColleague2 @
@colleague1.event()
@colleague2.event()
colleagueChanged: (colleague) ->
if colleague instanceof ConcreteColleague1
console.log 'colleague1 changed'
else if colleague instanceof ConcreteColleague2
console.log 'colleague2 changed'
class Example
@run: ->
m = new ConcreteMediator()
m.createColleagues()
Example.run()
class Memento
constructor: (@state) ->
getState: -> @state
class Originator
constructor: (@state) ->
setMemento: (memento) ->
@state = memento.getState()
return
createMemento: ->
new Memento @state
_changeState: (@state) ->
_showState: ->
console.log @state
class Caretaker
constructor: (@originator) ->
doCommand: ->
@state = @originator.createMemento()
@originator.setMemento @state
undoCommand: ->
@originator.setMemento @state
class Client
@run: ->
originator = new Originator 'foo'
caretaker = new Caretaker originator
originator._showState()
caretaker.doCommand()
originator._changeState 'bar'
originator._showState()
caretaker.undoCommand()
originator._showState()
Client.run()
class Subject
constructor: ->
@counter = 0
@observers = new List()
attach: (o) ->
o.__POINTER__ = @counter
@observers.append o
@counter += 1
detach: (o) ->
@observers.remove o
notify: ->
i = new ConcreteIterator @observers
while not i.isDone()
i.currentItem().update @
i.next()
class Observer
update: (theChangedSubject) ->
class ConcreteSubject extends Subject
class ConcreteObserver extends Observer
update: (theChangedSubject) ->
console.log 'Updated'
class Example
@run: ->
subject = new ConcreteSubject()
observer = new ConcreteObserver()
subject.attach observer
subject.notify()
Example.run()
class Context
constructor: (@strategy) ->
contextInterface: ->
@strategy.algorithmInterface()
class Strategy
algorithmInterface: ->
class ConcreteStrategyA extends Strategy
algorithmInterface: ->
console.log 'ConcreteStrategyA'
class ConcreteStrategyB extends Strategy
algorithmInterface: ->
console.log 'ConcreteStrategyB'
class ConcreteStrategyC extends Strategy
algorithmInterface: ->
console.log 'ConcreteStrategyC'
class Example
@run: ->
context = new Context new ConcreteStrategyA()
resultA = context.contextInterface
context = new Context new ConcreteStrategyB()
resultB = context.contextInterface
context = new Context new ConcreteStrategyC()
resultC = context.contextInterface
Example.run()
class AbstractClass
templateMethod: ->
@primitiveOperation1()
@primitiveOperation2()
primitiveOperation1: ->
primitiveOperation2: ->
class ConcreteClass extends AbstractClass
primitiveOperation1: ->
console.log 'primitiveOperation1'
primitiveOperation2: ->
console.log 'primitiveOperation2'
# Static Template Method
class StaticAbstractClass
@templateMethod: ->
cls = new @()
cls.primitiveOperation1()
cls.primitiveOperation2()
primitiveOperation1: ->
primitiveOperation2: ->
class StaticConcreteClass extends StaticAbstractClass
primitiveOperation1: ->
console.log 'primitiveOperation1'
primitiveOperation2: ->
console.log 'primitiveOperation2'
class Example
@run: ->
concrete = new ConcreteClass()
concrete.templateMethod()
StaticConcreteClass.templateMethod()
Example.run()
class List
constructor: ->
# A list of pointers
@items = []
# Objects passed in by pointer
@objects = {}
# Returns the number of objects in the list
count: ->
@items.length
# Returns the object at the given length
get: (index) ->
@objects[@items[index]]
# Returns the first object in the list
first: ->
@objects[@items[0]]
# Returns the last object in the list
last: ->
@objects[@items[@items.length - 1]]
# Adds the argument to the list, making it the last item
append: (item) ->
pointer = item.__POINTER__
@items.push pointer
@objects[pointer] = item
# Removes the given element from the list.
remove: (item) ->
pointer = item.__POINTER__
delete @objects[pointer]
index = pointer in @items
# delete @items[index] if index isnt -1
@items.splice index, 1
# Removes the last element from the list
removeLast: ->
@remove @last
# Removes the first element from the list
removeFirst: ->
@remove @first
# Removes all elements from the list
removeAll: ->
@items = []
@objects = {}
list = new List()
list.append __POINTER__: 'uniqueid', other: 'properties'