Android:存储库模式创建对象的最佳解决方案是什么?

yoo*_*hok 5 oop singleton design-patterns repository-pattern kotlin

这个问题是关于OOP(类/接口)设计的。

我正在开发一个 android 库,而不是一个应用程序。该应用程序将使用该库。该库是按照Repository模式开发的。

1 个存储库和 2 个数据源(本地、远程)。

因为本地数据源使用“SharedPreference”,所以需要Context。

下面是我的存储库界面和实现。

interface MyRepository {

    fun create(String data)

    fun get(key: String): String
}

class MyRepositoryImpl(
        private val localDataSource: LocalDataSource,
        private val remoteDataSource: RemoteDataSource
): MyRepository {

    fun create(String data) {
        localDataSource.create(data);
        remoteDataSource.create(data);
    }

    fun get(key: String): String {
        // temp code
        return localDataSource.get(key)
    }

    companion object {

        private var instance: MyRepository? = null

        fun getInstance(context: Context): MyRepository {
            if (instance == null) {
                val localDataSource: LocalDataSource = LocalDataSourceImpl.getInstance(context)
                val remoteDataSource: RemoteDataSource = RemoteDataSourceImpl.getInstance()
                instance = MyRepositoryImpl(localDataSource, remoteDataSource)
            }

            return instance!!
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

MyRepositoryImpl是通过Singleton模式实现的。因为它应该在应用程序中的任何地方使用。因此应用程序开发人员应该能够获取 MyRepository 的实例,如下所示:

val myRepository = MyRepositoryImpl.getInstance(context)
val data = myRepository.get("key")
Run Code Online (Sandbox Code Playgroud)

但它看起来很奇怪......“getInstance(context)”。我认为这不是一个好方法。请问还有更智能的设计吗?

Nic*_*zzi 8

在 Kotlin 中,您可以使用object关键字以线程安全的方式实现单例模式。无需在伴生对象中定义 getInstance 方法。只需将您的MyRepository类定义为对象,如下所示。通过重载调用运算符,您将能够传递对初始化 localDataSource 和 remoteDataSource 实例有用的上下文。

object MyRepository  {
    private lateinit var localDataSource: LocalDataSource
    private lateinit var remoteDataSource: RemoteDataSource

    operator fun invoke(context: Context): MyRepository {
        //...
        localDataSource = LocalDataSourceImpl.getInstance(context)
        remoteDataSource = RemoteDataSourceImpl.getInstance(context)
        return this
    }
}
Run Code Online (Sandbox Code Playgroud)

该代码将被编译为以下java代码(静态初始化块):

public final class MyRepository {
   public static final MyRepository INSTANCE;

   private SomeSingleton() {
      INSTANCE = (MyRepository) this;
   }

   static {
      new MyRepository();
   }
}
Run Code Online (Sandbox Code Playgroud)

这样,您就可以像普通的非对象类一样获取 MyRepository 类的实例,只需执行以下操作:

val repo = MyRepository(this) // this is your context
Run Code Online (Sandbox Code Playgroud)

您在类中定义的每个方法都MyRepository可以像 java 静态方法一样访问,因此您可以像这样调用它:

MyRepository.myMethod()
Run Code Online (Sandbox Code Playgroud)

更多详情请点击此处