有没有单例模式的最佳实践?

rt,有些合约不希望有多个实例,需要全局唯一,有什么好的方案吗?
我个人想到的是在 constructor 中写个 require 校验,指定只能由某个固定的 msg.sender 地址来创建。期待探讨更好的方式。

没有明白你这里所有的单例指的是什么?

是指一个合约只部署一次,然后让所有的其它合约来调用吗?
如果是这样,与谁来创建这个合约又有何关系呢?

singleton

设计模式的单例是 用于 全局共享数据,您说的单例具体要干什么? 有什么场景说一下吗?

因为区块链不可篡改的特性,我们想设计一个变通的方案来支持合约升级(修改)。参考了有个叫 r egistry pattern 的方案,即有个类似索引的全局唯一合约,用于记录合约的别名、地址、版本、是否生效,同时我们再扩展一些统计分析的功能(当然这些功能会限定使用者),所以单例模式是比较适合的。

如上所述,还是有点关系,因为该单例合约在功能上的有限制,不是完全开放给所有人。

Okay, 我理解你的意思并想了如下思路,你看行不行:

Step 1: 部署 global 合约

这个合约是调用其它合约的总入口,这个合约对你的客户提供服务,一旦部署,将不会改变。也就是这个合约部署后的地址不变,我暂记为 GlobalAddress

这个合约至少包括了注册子合约的接口:

register(SubContractsInfo)

SubContractsInfo 中至少包括了子合约的地址。

Step 2: 部署子合约

子合约可能有很多个,为了控制子合约接口的访问权限。在每个方法上添加 onlyGlobalAdress 的限制:

modifier onlyGlobalAdress () {
    require(msg.sendder == GlobalAddress, "Not the global address!")
    _
}

function xxxx onlyGlobalAdress {

}

部署子合约将会获得合约地址, 暂记为 SubAddress

Step 3: 在 Global 合约中注册 SubAddress

调用 Global 合约中的注册接口 register 注册子合约 SubAddress 。

Step 4: 子合约升级

  1. 子合约更改,重新部署,获得新的地址,暂记为 SubAddressNew ;
  2. 调用Global 合约中的注册接口 register 重新注册子合约 SubAddressNew。
  3. 完成合约升级。

不知道这样描述是不是你所想?