Kotlin Singleton:对象与具有私有构造函数的类

Kotlin Singleton:对象与具有私有构造函数的类,kotlin,singleton,Kotlin,Singleton,使用带有伴生对象的私有类来实现其存储库的单例模式,而不是简单地将存储库实现为(固有的单例)对象 这是我第一次在Kotlin中看到以这种方式实现的单例,而不是将其作为对象实现。在什么上下文中应该使用这个私有构造函数实现而不是更常见的对象实现 class GardenPlantingRepository private constructor( private val gardenPlantingDao: GardenPlantingDao ) { suspend fun createGar

使用带有伴生对象的私有类来实现其存储库的单例模式,而不是简单地将存储库实现为(固有的单例)对象

这是我第一次在Kotlin中看到以这种方式实现的单例,而不是将其作为对象实现。在什么上下文中应该使用这个私有构造函数实现而不是更常见的对象实现

class GardenPlantingRepository private constructor(
  private val gardenPlantingDao: GardenPlantingDao
) {
  suspend fun createGardenPlanting(plantId: String) {
    withContext(IO) {
      val gardenPlanting = GardenPlanting(plantId)
      gardenPlantingDao.insertGardenPlanting(gardenPlanting)
    }
  }

  suspend fun removeGardenPlanting(gardenPlanting: GardenPlanting) {
    withContext(IO) {
      gardenPlantingDao.deleteGardenPlanting(gardenPlanting)
    }
  }

  fun getGardenPlantingForPlant(plantId: String) =

    gardenPlantingDao.getGardenPlantingForPlant(plantId)

  fun getGardenPlantings() = gardenPlantingDao.getGardenPlantings()

  fun getPlantAndGardenPlantings() = gardenPlantingDao.getPlantAndGardenPlantings()

  companion object {
    // For Singleton instantiation
    @Volatile private var instance: GardenPlantingRepository? = null

    fun getInstance(gardenPlantingDao: GardenPlantingDao) =
      instance ?: synchronized(this) {
        instance ?: GardenPlantingRepository(gardenPlantingDao).also { instance = it }
      }
  }
}

如果您的单例实例需要参数(如本例中的参数),则使用
对象是一个问题,因为它们不能接受构造函数参数。这在Android上经常出现,因为在很多情况下,单身汉需要
上下文
来操作

在这些情况下,您仍然可以使用
对象
,但这可能不安全或不方便:

  • 第一个选项是在使用其任何其他方法之前,使用setter方法为其提供依赖项。这意味着其他每个方法都必须检查依赖项是否已经初始化,如果没有初始化,可能会抛出异常,这会导致运行时问题
  • 或者,您可以要求任何依赖项作为singleton的每个方法的参数,这在调用站点上非常繁琐
因此,使用私有构造函数和工厂方法来实现单例的“传统”方式被取代