Seaside Smalltalk 上的 uniqueInstance

uniqueInstance on Seaside Smalltalk

我正在尝试在 Seaside 上实现单例模式。 这是我的代码:

        uniqueInstance
            uniqueInstance ifNil: [ uniqueInstance := self createInstance].
            ^ uniqueInstance

    createInstance
        ^ self basicNew

initialize
    users:= OrderedCollection new.

在实例端,我有 users 这是实例变量。当我调用应用程序 uniqueInstance 初始化工作。当我检查用户变量时,它说 "Identity Set" 而不是 OrderedCollection.

任何人都可以解决我的错误吗?

您的 #createInstance 方法发送 #basicNew 消息,但这个方法不发送 #initialize。所以没有人初始化你的对象,users 仍然是 nil。必须有一些惰性方法将 users 设置为 IndentitySet,这就是你得到它的原因。但是没有人把它变成 OrderedCollection.

initialize实例使用#new而不是#basicNew;至少在 Pharo 和其他一些方言中 #new 会为你发送 #initialize

基于(Pharo)关于单例的邮件列表讨论,我前段时间写了一些变体 https://www.peteruhnak.com/blog/2015/12/06/singleton-variations/ .

但是单例的要点是:

  1. (通常)块 MyThing class>>new
    • 因为是单例
  2. 创建实例时调用super newself basicNew initialize
    • 这是为了绕过阻塞new;如果您的方言不自动调用 initialize 则使用后一种形式
  3. (可选)将 MyThing class>>reset 添加到 nil 实例
    • 主要是为了方便(使用 <script: 'self reset'> pragma 可以做得更好)

所以在你的情况下它可以是这样的:

Users class>>uniqueInstance
    ^ uniqueInstance ifNil: [ uniqueInstance := super new ]

Users class>>new
    self error: 'Users is a singleton -- send uniqueInstance instead'

Users>>initialize
    users:= OrderedCollection new

如果您在 Pharo,请随意探索现有的实现

MessageBrowser browse: (#uniqueInstance implementors select: #isMetaSide).
MessageBrowser browse: (#default implementors select: #isMetaSide).
MessageBrowser browse: (#current implementors select: #isMetaSide).