我可以在Scheme中实现这样的Singleton Design Pattern吗?

Ala*_*aya 2 scheme design-patterns

我对设计模式知之甚少,今天我学习了Singleton设计模式,所以我尝试在这样的Scheme中实现它

(define nil '())
(define Singleton
  (let ((instance nil))
    (lambda ()
      (if (null? instance)
          (let ((a 0))
            (define (dispatch msg)
              (cond ((eq? msg 'get)
                     (lambda () a))
                    ((eq? msg 'set)
                     (lambda (v) 
                       (begin (set! a v)
                              'ok)))))
              (set! instance dispatch)))
      instance)))
(define a (Singleton))
(define b (Singleton))
(eq? a b);;#t
((a 'set) 3)
((b 'get));;3
Run Code Online (Sandbox Code Playgroud)

是我对这种设计模式的理解和实现吗?

use*_*lpa 6

你的实现是正确的,因为(eq? a b)#t.

我会简化它(尽管这不是Code Review),如下所示:

  1. 如果是第一次通话,则无需拥有标志; 只需定义一次调度程序并不断返回对它的引用
  2. 没有必要定义nil,'()会做
  3. 我个人更喜欢使用(a 'set 3)而不是((a 'set) 3)
  4. 在这种情况下,使用它case代替更清楚cond

所以

(define Singleton
  (let ((a 0))                     ; instance variables
    (define (get) a)
    (define (set v) (set! a v) 'ok)
    (define (dispatch msg . args)  ; dispatcher procedure
      (case msg
        ((get) (apply get args))
        ((set) (apply set args))
        (else  (error "unknown message"))))
    (lambda () dispatch)))         ; return dispatch procedure
Run Code Online (Sandbox Code Playgroud)

然后

(define a (Singleton))
(define b (Singleton))
(eq? a b)    ;;  #t
(a 'set 3)   ;; 'ok
(b 'get)     ;;   3
Run Code Online (Sandbox Code Playgroud)