单例模式应该用来存储合约状态,或者当只需要一行时,作为多索引表的替代。
我们将探讨单例模式作为合约状态持久性的方法。使用table会浪费资源,因为我们的数据只会占用一行。
对于此示例,我们将使用单例来存储合约配置状态。让我们用结构来定义我们的单例。我们将使用一种bool类型closed
和uint32_t类型char_count
。我们可以用它来限制用户上传大小。
struct Config {
bool closed = false;
uint32_t char_count = 144;
};
typedef singleton<N(settings), Config> settings_table;
接下来,我们将为我们的实例创建一个占位符变量,使其在合同的上下文中成为全局变量。
settings_table config;
- 初始化Singleton
我们可以在每次使用它时或在我们的合约构造函数中初始化我们的单例,以便在我们的合约的每个操作中都可用。我们在这个例子中的合约被命名singletons
,但你可以称之为你想要的。
singletons(action_name self) : contract(self), config(_self, _self) {
if(config.exists()) {
_config = config.get();
} else {
_config.close = false;
}
}
- 与多索引表类似,初始化单例采用contract-code和scope。在这个例子中,我们将代码和范围都设置为
_self.
现在我们已经初始化了单例,我们可以通过读取char_count
值并将其打印到控制台来开始与值进行交互。
auto state = config.get();
print(state.char_count);
- 就是这样!我们
config.get()
检索先前初始化的单例并将其分配给state
变量。现在我们可以访问struct
使用点符号的属性。
在这个例子中,我们将char_count
使用成员函数更新属性singleton.set(STRUCT,PAYER)
让我们看两个方法来更新我们的单例。
方法1 - 内联更新
最简单的方法是构建我们的内联结构,将它直接传递给我们设置的set函数,就像这样;
config.set(Config{true, 172}, _self);
这里我们设置closed
为true,char_count
为172,同时委托_self
作为此RAM的付款人。当struct只包含几个属性并维护属性顺序时,此方法是干净的,但我们需要一个更好的方法来处理更大的结构。
方法2 - 检索和更新
接下来让我们使用fetch和update方法重新打开我们的合约。首先,我们将Config
使用该singleton.get()
方法获取当前状态,设置closed
值,然后再次设置状态。
auto state = config.get();
state.closed = false;
config.set(state, _self);
- 这就是单例模式,简单!在下一部分中,我们将研究多索引表索引,主要关注使用二级索引。