Android: 存储库模式创建对象的最佳解决方案是什么?
Android: repository pattern what is the best solution to create an object?
这个问题是关于 OOP(class/interface) 设计的。
我正在开发 android 库,而不是应用程序。
该应用程序将使用此库。
本库采用 Repository 模式开发。
一个存储库和 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!!
}
}
}
MyRepositoryImpl采用单例模式实现。
因为它应该在应用程序的任何地方使用。
所以应用程序开发人员应该能够像这样获取 MyRepository 的实例:
val myRepository = MyRepositoryImpl.getInstance(context)
val data = myRepository.get("key")
但是看起来很奇怪……"getInstance(context)"。
我认为这不是一个好方法。
请问还有更巧妙的设计吗?
在 Kotlin 中,您可以使用 object 关键字以线程安全的方式实现单例模式。无需在伴随对象中定义 getInstance 方法。只需将您的 MyRepository
class 定义为如下所示的对象。通过重载调用运算符,您将能够传递对初始化 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
}
}
此代码将编译为以下 java 代码(静态初始化块):
public final class MyRepository {
public static final MyRepository INSTANCE;
private SomeSingleton() {
INSTANCE = (MyRepository) this;
}
static {
new MyRepository();
}
}
这样您就可以像普通的非对象 class 一样获取 MyRepository class 的实例,只需执行以下操作:
val repo = MyRepository(this) // this is your context
您在 MyRepository
class 中定义的每个方法都可以像 java 静态方法一样访问,因此您可以像这样调用它:
MyRepository.myMethod()
更多详情here
这个问题是关于 OOP(class/interface) 设计的。
我正在开发 android 库,而不是应用程序。 该应用程序将使用此库。 本库采用 Repository 模式开发。
一个存储库和 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!!
}
}
}
MyRepositoryImpl采用单例模式实现。 因为它应该在应用程序的任何地方使用。 所以应用程序开发人员应该能够像这样获取 MyRepository 的实例:
val myRepository = MyRepositoryImpl.getInstance(context)
val data = myRepository.get("key")
但是看起来很奇怪……"getInstance(context)"。 我认为这不是一个好方法。 请问还有更巧妙的设计吗?
在 Kotlin 中,您可以使用 object 关键字以线程安全的方式实现单例模式。无需在伴随对象中定义 getInstance 方法。只需将您的 MyRepository
class 定义为如下所示的对象。通过重载调用运算符,您将能够传递对初始化 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
}
}
此代码将编译为以下 java 代码(静态初始化块):
public final class MyRepository {
public static final MyRepository INSTANCE;
private SomeSingleton() {
INSTANCE = (MyRepository) this;
}
static {
new MyRepository();
}
}
这样您就可以像普通的非对象 class 一样获取 MyRepository class 的实例,只需执行以下操作:
val repo = MyRepository(this) // this is your context
您在 MyRepository
class 中定义的每个方法都可以像 java 静态方法一样访问,因此您可以像这样调用它:
MyRepository.myMethod()
更多详情here