App 组件化/模块化之路——Repository 模式

简介: 什么是 Repository 模式 Repository 这个词直译过来仓库、仓储的意思。这个意思其实也能反应出 Repository 模式作用。App 开发中少不了对数据的操作,数据的来源可能有很多种:网络、数据库、文件以及内存中的缓存。

什么是 Repository 模式

Repository 这个词直译过来仓库、仓储的意思。这个意思其实也能反应出 Repository 模式作用。App 开发中少不了对数据的操作,数据的来源可能有很多种:网络、数据库、文件以及内存中的缓存。而 Repository 就相当于一个仓库管理员,管理这些数据的存储。当业务层想要获取或者存储数据时,只需要通过 Repository 的管理员进行操作。这样的好处就是:屏蔽数据来源的操作接口。对于业务层来说不必关心数据存在哪里,以及如何存储的。而且也符合我们组件化/模块化架构设计的思想。即当我们更换数据存储设备时,例如从 Android 系统 Sqlite 数据转换为第三方的数据库时,不会影响到业务逻辑。

设计模式

首先预览一下 Repository 模式的设计类图(欢迎拍砖)

Repository模式

IDataSource 是定义了数据来源接口,是根据具体的业务需要定义。一般来说,有增、删、改、查这几个方法。

LocalRepository 封装的是本地存储方式,实现 IDataSource 接口。

RemoteRepository 封装的是网络存储方式,实现 IDataSource 接口。

其中 LocalRepositoryRemoteRepository 就是代表着各种存储方式的具体实现。而 RepositoryFactory就是传说中的“仓库管理员”,管理着各种存储方式,它也是业务层数据层交互的桥梁。

Show me the code

假设目前有个业务是获取远程数据的需求,如果本地有缓存数据则从本地获取,否则从网络中获取。这样的业务逻辑很常见,我们用 Repository

模式进行封装。

首先预览代码总体结构

repository-code-structure

IDataSource

public interface IDataSource<T> {
    void add(T t);

    void delete(T t);

    void update(T t);

    List<T> queryAll();

    T queryById(int id);
}

 

LocalRepository

public class LocalRepository implements IDataSource<Data> {

    public LocalRepository() {
    }

    @Override
    public void add(Data data) {
        DBHelper.get().add(data);
    }

    @Override
    public void delete(Data data) {
        DBHelper.get().delete(data);
    }

    @Override
    public void update(Data data) {
        DBHelper.get().update(data);
    }

    @Override
    public List<Data> queryAll() {
        return DBHelper.get().queryAll();
    }

    @Override
    public Data queryById(int id) {
        return DBHelper.get().queryById(id);
    }
}

 

RemoteRepository

public class RemoteRepository implements IDataSource<Data> {
    @Override
    public void add(Data data) {
        DataApi.get().add(data);
    }

    @Override
    public void delete(Data data) {
        DataApi.get().delete(data);
    }

    @Override
    public void update(Data data) {
        DataApi.get().update(data);
    }

    @Override
    public List<Data> queryAll() {
        return DataApi.get().queryAll();
    }

    @Override
    public Data queryById(int id) {
        return DataApi.get().queryById(id);
    }
}

 

RepositoryFactory

public class RepositoryFactory implements IDataSource<Data> {
    private IDataSource<Data> local;
    private IDataSource<Data> remote;

    private static RepositoryFactory INSTANCE;
    /**
     * 使用Map实现一个内存缓存
     */
    HashMap<String, Data> mCache = new HashMap<>();

    private RepositoryFactory(@NonNull IDataSource<Data> local, @NonNull IDataSource<Data> remote) {
        this.local = local;
        this.remote = remote;
    }

    public static RepositoryFactory get(@NonNull IDataSource<Data> local, @NonNull IDataSource<Data> remote) {
        if (INSTANCE == null) {
            INSTANCE = new RepositoryFactory(local, remote);
        }
        return INSTANCE;
    }

    public static RepositoryFactory get() {
        if (INSTANCE == null) {
            INSTANCE = new RepositoryFactory(new LocalRepository(), new RemoteRepository());
        }
        return INSTANCE;
    }

    public void destory() {
        INSTANCE = null;
    }

    @Override
    public void add(Data data) {
        local.add(data);
        remote.add(data);
        mCache.put(String.valueOf(data.id), data);
    }

    @Override
    public void delete(Data data) {
        local.delete(data);
        remote.delete(data);
        mCache.remove(String.valueOf(data.id));
    }

    @Override
    public void update(Data data) {
        local.update(data);
        remote.update(data);
        mCache.put(String.valueOf(data.id), data);
    }

    /**
     * @return
     */
    @Override
    public List<Data> queryAll() {
        List<Data> list = local.queryAll();
        if (list.isEmpty()) {
            list = remote.queryAll();
        }
        return list;
    }

    /**
     * 这里使用三级缓存获取一个Data对象
     *
     * @param id
     * @return
     */
    @Override
    public Data queryById(int id) {

        Data data = mCache.get(String.valueOf(id));
        if (data == null) {
            data = local.queryById(id);
        }
        if (data == null) {
            data = remote.queryById(id);
        }
        if (data != null) {
            mCache.put(String.valueOf(id), data);
        }
        return data;
    }

}

 

使用示例

Flowable.fromCallable(new Callable<List<Data>>() {
            @Override
            public List<Data> call() throws Exception {
                List<Data> dataList = RepositoryFactory.get().queryAll();
                return dataList;
            }
        }).observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Consumer<List<Data>>() {
                    @Override
                    public void accept(@NonNull List<Data> datas) throws Exception {
                        textView.setText("data size:" + datas.size());
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(@NonNull Throwable throwable) throws Exception {
                        textView.setText(throwable.getMessage());
                    }
                });

 

这里是直接使用了 RxJava2 进行调用,因为 Repository 是对数据的请求和访问,这个是耗时操作,故需要放在后台线程中进行。在实际的项目中一般都会使用 MVP 来封装这一层。

本文Demo :wecodexyz/Componentization

参考文献:googlesamples/android-architecture

目录
相关文章
|
6月前
|
传感器 人工智能 数据可视化
Java智慧工地监管一体化云平台APP源码 SaaS模式
安全隐患排查 1.可在电脑端、手机端对安全隐患数据进行记录、查询 2.能够实现安全隐患发起、整改、复查的闭环管理 3.具备对安全隐患数据进行统计、可视化分析、信息推送等功能 4.包含对危险性较大的分部分项工程进行巡查记录功能
131 4
|
15天前
|
开发工具 git C++
【App Service】VS Code直接部署App Service时候遇见 “fatal: not a git repository (or any of the parent directories): .git”
通过VS Code发布Python App Service的时候,遇见了发布失败错误: The deployment failed with error: fatal: not a git repository (or any of the parent directories): .git . Please take a few minutes to help us improve the deployment experience
69 24
|
3月前
|
消息中间件 Java
【实战揭秘】如何运用Java发布-订阅模式,打造高效响应式天气预报App?
【8月更文挑战第30天】发布-订阅模式是一种消息通信模型,发送者将消息发布到公共队列,接收者自行订阅并处理。此模式降低了对象间的耦合度,使系统更灵活、可扩展。例如,在天气预报应用中,`WeatherEventPublisher` 类作为发布者收集天气数据并通知订阅者(如 `TemperatureDisplay` 和 `HumidityDisplay`),实现组件间的解耦和动态更新。这种方式适用于事件驱动的应用,提高了系统的扩展性和可维护性。
64 2
|
3月前
|
开发工具 git
【Azure 应用服务】App Service 开启了私有终结点(Private Endpoint)模式后,如何来实现公网Git部署呢?
【Azure 应用服务】App Service 开启了私有终结点(Private Endpoint)模式后,如何来实现公网Git部署呢?
|
3月前
|
前端开发 JavaScript PHP
【Azure 应用服务】App Service 在使用GIt本地部署,上传代码的路径为/home/site/repository,而不是站点的根目录/home/site/wwwroot。 这个是因为什么?
【Azure 应用服务】App Service 在使用GIt本地部署,上传代码的路径为/home/site/repository,而不是站点的根目录/home/site/wwwroot。 这个是因为什么?
|
5月前
|
监控 小程序 前端开发
基础入门-抓包技术&HTTPS协议&WEB&封包监听&网卡模式&APP&小程序
基础入门-抓包技术&HTTPS协议&WEB&封包监听&网卡模式&APP&小程序
162 0
|
6月前
|
人工智能 监控 数据可视化
Java智慧工地云平台源码带APP SaaS模式 支持私有化部署和云部署
智慧工地是指应用智能技术和互联网手段对施工现场进行管理和监控的一种工地管理模式。它利用传感器、监控摄像头、人工智能、大数据等技术,实现对施工现场的实时监测、数据分析和智能决策,以提高工地的安全性、效率和质量(技术架构:微服务+Java+Spring Cloud +UniApp +MySql)。
126 4
|
6月前
|
前端开发 中间件 程序员
app的组件化之路:业务组件化与中间件,MVVM架构的作用
app的组件化之路:业务组件化与中间件,MVVM架构的作用
76 0
|
6月前
|
移动开发 前端开发 程序员
支付功能在app中的实现及支付功能模块化调用流程图
支付功能在app中的实现及支付功能模块化调用流程图
54 0
|
6月前
|
传感器 人工智能 数据可视化
Java智慧工地监管一体化云平台APP源码 SaaS模式
高支模监测:高支模立杆及倾斜角度,高支模立杆的荷载,架体的水平位移以及模板沉降情况,当检测数据超过预警值时,实时报警。
102 2