带有存储库工厂的存储库模式
Repository Pattern with Repository Factory
我正在尝试改进我的 Android 持久层以跨多个应用程序使用。
到目前为止我所做的是设置一个基本存储库摘要class和一个基本存储库接口,完整的代码可以在这里查看:https://github.com/grmaciel/android-repository-ormlite
接口:
public interface IRepository<T, Id> {
public void save(T entity) throws SQLException;
public void saveBatch(List<T> entities) throws Exception;
public List<T> queryAll() throws SQLException;
public T findById(Id id) throws SQLException;
public void delete(T entity) throws SQLException;
}
现在我所有的存储库都扩展了我的基本存储库,如下所示:
public class DependencyRepository extends BaseRepository<Dependency>
implements IDependenceyRepository {
public DependencyRepository(Context context) {
super(context);
}
}
我现在想要实现的是创建一个存储库工厂,让人们不必使用 new Instance()
到处实例化他们的存储库
我所做的是创建一个必须使用具有 class 关系的容器初始化的单例工厂,如下所示:
public abstract class BaseRepositoryContainer {
private final Context context;
public BaseRepositoryContainer(Context context) {
this.context = context;
}
public abstract <T extends IRepository> Map<Class<T>, Class<T>> getRepositoriesMap();
public Context getContext() {
return context;
}
}
工厂:
public class RepositoryFactory {
private Map<Object, Object> repositories = new HashMap<>();
private final String LOG_TAG = RepositoryFactory.class.getSimpleName();
private Context context;
private static RepositoryFactory instance;
private BaseRepositoryContainer container;
private RepositoryFactory() {}
public void init(BaseRepositoryContainer container) {
this.container = container;
this.context = container.getContext();
this.configureRepositories(container.getRepositoriesMap());
}
private <T extends IRepository> void configureRepositories(Map<Class<T>, Class<T>> repositoriesMap) {
for (Entry<Class<T>, Class<T>> entry : repositoriesMap.entrySet()) {
this.registerRepository(entry.getKey(), entry.getValue());
}
}
private <T extends IRepository> void registerRepository(Class<T> repInterface, Class<T> realRepository) {
repositories.put(repInterface, this.createRepository(realRepository));
}
public <T extends IRepository> T getRepository(Class<T> repInterface) {
if (container == null) {
throw new UnsupportedOperationException("You should call init method providing a container.");
}
return (T) repositories.get(repInterface);
}
private <T extends IRepository> T createRepository(Class<T> repoClass) {
try {
T instance = repoClass.getConstructor(Context.class).newInstance(context);
Log.d(LOG_TAG, "Repository " + repoClass.getSimpleName() + " created");
return instance;
} catch (InstantiationException e) {
Log.d(LOG_TAG, e.toString());
} catch (IllegalAccessException e) {
Log.d(LOG_TAG, e.toString());
} catch (InvocationTargetException e) {
Log.d(LOG_TAG, e.toString());
} catch (NoSuchMethodException e) {
Log.d(LOG_TAG, e.toString());
}
return null;
}
public static RepositoryFactory getInstance() {
if (instance == null) {
instance = new RepositoryFactory();
}
return instance;
}
}
然后可以这样调用:
// when the application is first run
RepositoryFactory.getInstance().init(new RepositoryContainer(this));
// retrieving the repository
IDependenceyRepository repository = RepositoryFactory.getInstance()
.getRepository(IDependenceyRepository.class);
所以我想知道这是否是帮助实现抽象的好方法?我不太喜欢调用工厂的 init 方法而不强制人们这样做的想法,唯一知道的方法是如果你不调用会抛出一个我不喜欢的异常。
有谁能给我指出正确的方向吗?改进此设计的方法?我不想稍后在我的项目中发现我已经创建了很多强依赖性并且很难改变某些东西。
如有任何建议,我们将不胜感激。
我没有重新发明轮子来改进我的代码,而是开始使用依赖注入库 (Dagger 2 - http://google.github.io/dagger/)。
您可以根据需要定义 return 跨应用程序或活动所需存储库的模块。
我正在尝试改进我的 Android 持久层以跨多个应用程序使用。
到目前为止我所做的是设置一个基本存储库摘要class和一个基本存储库接口,完整的代码可以在这里查看:https://github.com/grmaciel/android-repository-ormlite
接口:
public interface IRepository<T, Id> {
public void save(T entity) throws SQLException;
public void saveBatch(List<T> entities) throws Exception;
public List<T> queryAll() throws SQLException;
public T findById(Id id) throws SQLException;
public void delete(T entity) throws SQLException;
}
现在我所有的存储库都扩展了我的基本存储库,如下所示:
public class DependencyRepository extends BaseRepository<Dependency>
implements IDependenceyRepository {
public DependencyRepository(Context context) {
super(context);
}
}
我现在想要实现的是创建一个存储库工厂,让人们不必使用 new Instance()
我所做的是创建一个必须使用具有 class 关系的容器初始化的单例工厂,如下所示:
public abstract class BaseRepositoryContainer {
private final Context context;
public BaseRepositoryContainer(Context context) {
this.context = context;
}
public abstract <T extends IRepository> Map<Class<T>, Class<T>> getRepositoriesMap();
public Context getContext() {
return context;
}
}
工厂:
public class RepositoryFactory {
private Map<Object, Object> repositories = new HashMap<>();
private final String LOG_TAG = RepositoryFactory.class.getSimpleName();
private Context context;
private static RepositoryFactory instance;
private BaseRepositoryContainer container;
private RepositoryFactory() {}
public void init(BaseRepositoryContainer container) {
this.container = container;
this.context = container.getContext();
this.configureRepositories(container.getRepositoriesMap());
}
private <T extends IRepository> void configureRepositories(Map<Class<T>, Class<T>> repositoriesMap) {
for (Entry<Class<T>, Class<T>> entry : repositoriesMap.entrySet()) {
this.registerRepository(entry.getKey(), entry.getValue());
}
}
private <T extends IRepository> void registerRepository(Class<T> repInterface, Class<T> realRepository) {
repositories.put(repInterface, this.createRepository(realRepository));
}
public <T extends IRepository> T getRepository(Class<T> repInterface) {
if (container == null) {
throw new UnsupportedOperationException("You should call init method providing a container.");
}
return (T) repositories.get(repInterface);
}
private <T extends IRepository> T createRepository(Class<T> repoClass) {
try {
T instance = repoClass.getConstructor(Context.class).newInstance(context);
Log.d(LOG_TAG, "Repository " + repoClass.getSimpleName() + " created");
return instance;
} catch (InstantiationException e) {
Log.d(LOG_TAG, e.toString());
} catch (IllegalAccessException e) {
Log.d(LOG_TAG, e.toString());
} catch (InvocationTargetException e) {
Log.d(LOG_TAG, e.toString());
} catch (NoSuchMethodException e) {
Log.d(LOG_TAG, e.toString());
}
return null;
}
public static RepositoryFactory getInstance() {
if (instance == null) {
instance = new RepositoryFactory();
}
return instance;
}
}
然后可以这样调用:
// when the application is first run
RepositoryFactory.getInstance().init(new RepositoryContainer(this));
// retrieving the repository
IDependenceyRepository repository = RepositoryFactory.getInstance()
.getRepository(IDependenceyRepository.class);
所以我想知道这是否是帮助实现抽象的好方法?我不太喜欢调用工厂的 init 方法而不强制人们这样做的想法,唯一知道的方法是如果你不调用会抛出一个我不喜欢的异常。
有谁能给我指出正确的方向吗?改进此设计的方法?我不想稍后在我的项目中发现我已经创建了很多强依赖性并且很难改变某些东西。
如有任何建议,我们将不胜感激。
我没有重新发明轮子来改进我的代码,而是开始使用依赖注入库 (Dagger 2 - http://google.github.io/dagger/)。
您可以根据需要定义 return 跨应用程序或活动所需存储库的模块。