【问题标题】:How to make a data class singleton in Kotlin?如何在 Kotlin 中制作数据类单例?
【发布时间】:2019-10-09 19:14:52
【问题描述】:

假设我有一个数据类:

data class SensorData(val name: String, val temp : Double)

我从 REST 服务或通过内部 setter 方法创建此 SensorData 对象,而 name 始终填充,temp 可能为空。

此外,我通过几个类需要这个 SensorData 对象,这就是我想到的使用 singleton

显然我需要object 关键字as described here,但是我如何结合data class object 呢?

【问题讨论】:

  • 为此目的使用单例是错误的。只需将实例传递给需要它的类。

标签: kotlin singleton data-class


【解决方案1】:

我认为你对单例的概念理解错了:

“单例模式是一种软件设计模式,它将类的实例化限制为一个“单一”实例”

它不仅用于将其公开给所有类,还用于限制实例的数量。

数据类是存储数据的类,为什么要Singleton?

重新考虑您的架构,使其可在您需要的地方访问。

【讨论】:

    【解决方案2】:

    您可以使用伴随对象来保留对您的数据对象的引用:

    data class SensorData(val name: String, var temp : Double) {
        companion object {
            @Volatile
            @JvmStatic
            private var INSTANCE: SensorData? = null
    
            @JvmStatic
            @JvmOverloads
            fun getInstance(name: String = "default", temp : Double = 0.0): SensorData = INSTANCE ?: synchronized(this) {
                INSTANCE ?: SensorData(name, temp).also { INSTANCE = it }
            }
        }
    }
    

    并像这样使用它:

    val name1 = SensorData.getInstance("name", 5.0).name
    
    // Or with default values:
    val name2 = SensorData.getInstance().name
    

    【讨论】:

    • 在不知道传感器名称的情况下温度变化会发生什么?
    • 如果你想改变温度,请使用SensorData.getInstance().temp = 36.6。但在这种情况下,如果 INSTANCE 尚未初始化,名称将设置为 "default" 或您提供的任何默认值。
    【解决方案3】:

    不要将数据类用作单例。这不是他们的设计目的。更好的方法是围绕您的数据类创建一个包装器对象,该对象处理您的 SensorData-Object(s)。这也将允许您使用多个 SensorData 对象(将来可能需要),或者如果您第二次轮询 REST 服务,则将当前对象替换为新对象。

    object SensorDataService {
     var sensorData: SensorData? = null
    }
    
    data class SensorData(val name: String, val temp : Double)
    

    【讨论】:

    • 你永远不应该将可变数据放在单例对象中。全局共享可变数据是一个很大的禁忌。
    • @marstran 肯定是,但它也是对原始问题的回答。只要提供了一些初始化逻辑,sensorData 的设置器就可以是私有的。
    • @marstran 有什么例子吗?
    • @NoamSilverstein 这是一个关于它的 SO 问题:stackoverflow.com/questions/44219903/…
    • 共享可变数据将您的数据暴露给并发写入访问。数据可以由多个线程同时更改。假设您共享一个 int 变量 (i = 3)。一个线程加 +1,另一个线程乘以 2。根据哪个线程更快,您有 (3 + 1) * 2 = 8 或 3 * 2 + 1 = 7。哪个结果是正确的:7 还是 8?计算不正确的情况如何处理?
    猜你喜欢
    • 2019-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多