;; -*- gauche -*- (use srfi-1) ;; approach using Gauche's class system ;; base class (define-class () ()) (define-method initialize ((self ) initargs) (next-method) ; muoy importante... (print "initialize " self " with " initargs)) ;; subject (define-class () ((observers :init-value '()) (counter :init-value 0 :accessor counter-of))) (define-method do-something ((self )) (print "do-something") ;(slot-set! self 'data (+ 1 (slot-ref self 'data))) ;(slot-set! self 'data (+ 1 (data self))) ;(set! (counter-of self) (+ 1 (counter-of self))) (inc! (counter-of self)) (notify self)) (define-method attach ((self ) (obs )) (slot-set! self 'observers (cons obs (slot-ref self 'observers)))) ;; todo detach (define-method notify ((self )) (print "subject " self " will notify with " (counter-of self)) (dolist (obs (slot-ref self 'observers)) (update obs (counter-of self)))) ;; observer (define-class () ((name :init-keyword :name))) (define-method update ((self ) data) (format #t "observer ~s: new data ~s\n" (slot-ref self 'name) data)) (let ((subject (make )) (observer-a (make :name 'aap)) (observer-b (make :name 'noot))) (attach subject observer-a) (do-something subject) (attach subject observer-b) (do-something subject)) ;; ----------------------------------------------------------------- ;; classic closure approach (define (make-subject) (let ((observers '()) (data 0)) (define (do-something) (inc! data) (notify)) (define (attach subject) (push! observers subject)) (define (detach subject) (delete! subject observers)) (define (notify) (dolist (o observers) (o 'update data))) (lambda args (apply (case (car args) ((do-something) do-something) ((attach) attach) ((detach) detach) ((notify) notify) (else (print "subject: unknown method " (car args)))) (cdr args))))) (define (make-observer name) (let ((id name)) (define (update data) (format #t "~s: update ~s\n" id data)) (lambda args (apply (case (car args) ((update) update) (else (print "observer: unknown method " (car args)))) (cdr args))))) ;; (let ((subject (make-subject)) ;; (observer-a (make-observer 'aap)) ;; (observer-b (make-observer 'noot))) ;; (subject 'attach observer-a) ;; (dotimes (i 2) (subject 'do-something)) ;; (subject 'attach observer-b) ;; (dotimes (i 2) (subject 'do-something)) ;; (subject 'detach observer-a) ;; (dotimes (i 2) (subject 'do-something)))