如何使用 coffeescript 实现观察者

How to implement an observer with coffeescript

我尝试在 coffeescript 中实现观察者模式,例如 wikipedia observer pattern。如何使用 coffeescript 完成此操作?

像这样创建一个 class:

class Observer
  constructor: () ->
    @subscribers = {}
  notify: (to, arg...) ->
    if @subscribers[to]
      for cb in @subscribers[to].callback 
        try
          cb.apply @,[to].concat arg
        catch err
          console.log to+" "+(arg?.join ', ')+": "+err
  subscribe: (to, cb) ->
    if @subscribers[to]==undefined || @subscribers[to].callback.size==0
      @subscribers[to]={'callback':[cb]}
    else
      @subscribers[to].callback.push cb if cb not in @subscribers[to].callback
  unsubscribe: (to, cb) ->
    @subscribers[to]?.callback.splice @subscribers[to].callback.indexOf(cb), 1

使用方法

### Define subscriber ###
class SubscriberA
  onEvent: (item) ->
    console.log item

class SubscriberB
  onEvent: (item) ->
    console.log item

class SubscriberC
  onEventTypeA: (item) ->
    console.log "EventTypeA: "+item

  onEventTypeB: (item) ->
    console.log "EventTypeB: "+item

class SubscriberD
  onEventTypeA: (item,arg="23 is default") ->
    console.log item+" "+arg
  onEventTypeB: (item,arg...) ->
    console.log item + " with: "
    for a in arg
      console.log a

### Create observer ###
myO = new Observer()

### Create subscribing objects
   In real live this would be your objects that will have to provide a function that handels notifications. Within this example they are called onEventXYZ
###
subscriptionOfA = new SubscriberA()
subscriptionOfB = new SubscriberB()
subscriptionOfC = new SubscriberC()
subscriptionOfD = new SubscriberD()

console.log ": Subscribe Peter once and Paul twice"
myO.subscribe "Peter", subscriptionOfA.onEvent
myO.subscribe "Paul", subscriptionOfA.onEvent
myO.subscribe "Paul", subscriptionOfA.onEvent

console.log ": Notify Peter and Paul"
myO.notify "Peter"
myO.notify "Paul"

console.log ": Paul is only notified once as duplicate subscriptions are ignored while subscribe"
console.log ": Subscribe Paul with a different subscriber"
myO.subscribe "Paul", subscriptionOfB.onEvent
console.log ": Notify Peter and Paul"
myO.notify "Peter"
myO.notify "Paul"

console.log ": Paul is notified twice as two different subscriptions are subscribed"

console.log "\n: Unsubscribe Peter"
myO.unsubscribe "Peter"
console.log ": Notify Peter and Paul"
myO.notify "Peter"
myO.notify "Paul"


console.log "\n: Not subscribed items will be ignored at notify"
console.log ": Notify Bob"
myO.notify "Bob"

console.log "\n: You may use multiple eventHandler in your subsribers"

myO.subscribe "Mary", subscriptionOfC.onEventTypeA
myO.subscribe "Jane", subscriptionOfC.onEventTypeB

console.log ": Notify Mary and Jane"
myO.notify "Mary"
myO.notify "Jane"

console.log "\n: You may use arguments with your eventHandler"

myO.subscribe "Laurel", subscriptionOfD.onEventTypeA
myO.subscribe "Hardy", subscriptionOfD.onEventTypeB

console.log ": Notify Laurel without argument"
myO.notify "Laurel"
console.log ": Notify Laurel with argument"
myO.notify "Laurel", 42
console.log ": Notify Hardy with multiple arguments"
myO.notify "Hardy", "Argument String",1,2,3,['a','b']