AI实践哪家强?来 AICon, 解锁技术前沿,探寻产业新机! 了解详情
写点什么

Android 模块化:面向接口编程

  • 2020-02-12
  • 本文字数:3507 字

    阅读完需:约 12 分钟

Android模块化:面向接口编程

一、概述

随着业务的发展,工程的逐渐增大与开发人员增多,很多工程都走向了模块化、组件化、插件化道路,来方便大家的合作开发与降低业务之间的耦合度。现在就和大家谈谈模块化的交互问题,首先看下模块化的几个优势。

模块化的优势

  1. 结构清晰:业务独立,代码实现分离,不会搅在一起。

  2. 便于协作:每个开发同学只要自己负责的模块,没有太多的耦合。

  3. 便于维护:各模块管理自己的代码、布局、资源,主工程可以方便添加与移除。


特点:高内聚、低耦合。

常见的模块化实现方式有两种

  1. 业务 Module 都放到同一个工程里。

  2. 每个业务 Module 都是一个独立的工程。


如图:



模块的划分

模块可分为多种类型,一般分为:三方的基础 SDK (网络请求,地图导航,推送等);自己平台的通用功能(网络请求的能力封装、图片加载能力封装、权限设置、UI 组件等);业务模块的拆分(登录、交易、会员、硬件等)。


模块间通信

虽然功能已经按模块拆分,但是模块间通信也是多种形势,如果处理不好模块之间耦合严重维护成本增大。常见模块问通信有:直接依赖、事件或广播通信、路由通信、面向接口通信,下面就对比下几种通信优势。

二、实现方案

直接依赖


这种方式实现简单,但是耦合太严重,不方便维护与开发,当工程逐渐增大模块逐渐增多,依赖关系会非常复杂,不推荐这种方式。

事件或广播通信

EventBus:我们非常熟悉的事件总线型的通信框架,非常灵活,采用注解方式实现,但是难以追溯事件。


广播:安卓的四大组件之一,在一个模块中发送广播设置数据,在另一个模块中注册广播接收数据,使用广播进行数据传递方式广播相对于其他的方式而言消耗资源较多。


总结:BroadcastReceiver、EventBus,非常灵活,模块之间没有任何的耦合,但是代码的可读性差,难以追溯事件,不是很推荐。

路由通信

模块与模块之间不存在依赖关系,而是各自运作,简单的来说就是映射关系的路由通信,也是目前比较主流的一种方案,比较常用的开源框架是阿里的 ARouter。


ARouter 典型应用


从外部 URL 映射到内部页面,以及参数传递与解析跨模块页面跳转,模块间解耦拦截跳转过程处理登陆、埋点等逻辑跨模块 API 调用,通过控制反转来做组件解耦。

面向接口通信

以上几种方式只是简单的介绍,下面就具体说下通过接口解耦通信的方式,首先先看几个问题。


什么是面向接口编程?


接口大家都很熟悉,这里所说的面向接口编程,并不只是所谓的 java 中的 interface,而是指超类型,可以是接口也可以是抽象类。


面向接口比面向对象编程是更先进一步编程思想,而是附属于面向对象编程的体系,属于其中一部分,它是面向对象编程体系中的思想精髓之一。面向接口编程它的核心思想是将抽象与实现分离,从组件的级别来设计代码,达到高内聚低耦合的目的。面向接口编程方法是,先定义底层接口模块,也就是 通信的协议与功能约定,是提供方实现对应的功能与能力。在架构中层次分明,不需要关注具体实现,开发中可以通过接口快速制定协议,与提供能力 api,对于上层通过接口显露能力,对于下层只需要依赖接口层相当于依赖 api。


面向接口编程的好处?


灵活性高没有依赖具体的实体,实现层可以任意的更改与切换。在模块化中可以相互依赖 service(接口层)或依赖多个。


‍在模块化中的使用下面对于接口(interface)或 api 层统称为 service,其含义为服务提供者。



对于,每一个 module 都一个独立的工程结构,每个 module 都有自己的 Service ,来统一暴露当前 module 所拥有能力与向外提供的服务。



对于 module 是在同一个工程里的项目结构,service 可以放到统一的一个 Module 下,我们统称为 Mediator,这样做的目的是为了减少 Module 创建与维护。假设你的工程有 20 个业务 Module 如果都同时增加一个 service 层就会造成 Module 数量翻一倍。由于这里存入的都一些接口类,也是每个业务 Module 向外提供的服务其体量不会太大,这里并只是一个建议并没有标准的做法。


当然也有更复杂的设计,一个 Module 又分不同的 service 实现如图,这里不在展开细说。


实际工程中使用与设计

在实际项目中有很多项目都同时开发两版本 Pad 与 Phone,有的是两独立的工程,有的是在同一个工程内用 flavor 切换不同的工程,下面我就以通过 flavor 切换的工程结构举例。


先看下工程的包的结构图:



可以看到 module 结构是分为三个部分,common, pad, phone, 如果每个 service 都独立将增加 3 倍的 Module 数量。



使用一个 Mediator Module 统一管理这这些 service 就很好控制了 module 数量。

Service 创建

在 module_mediator 业务 module 下 common,pad、pone 下分别创建 ICommonService, IService(pad), IService(phone)。ICommonService:公共服务。IService(pad):pad 服务并继承 CommonService。IService(phone):phone 服务并继承 CommonService。



注:这里为什么不用,PadService 与 PhoneService,是因为 pad 与 phone 版本同时只会存在一个,使用方只需要关心你提供的 Service 不用在区分版本,而且这里是一个继承关系也可以获取到共用的部分。

Service 实现

依赖 Mediator :



在业务 common\pad\phone module 下分别实现,ICommonService, Service(pad), IService(phone) ,在 common module 创建 CommonServiceImpl 实现 ICommonService,在 pad、phone module 分别创建 ServiceImpl 对应实现 IService 并继承与 CommonServiceImpl。


Service 注册

注册的方式有一般是通过代码用去注册,或通过注解进行注册。可以在 Application 注册也可以在业务 Module 下自己注册,如果使用注解则可以自动注册,具体要看项目怎样实现。例:




解释下 MediatorServiceFacator,它只是一个服务工厂也是一个接口类,作用是负责管理各业务方的 Service 主要功能是注册与获取 Service。上面的代码就是往里注册了一个会员的 Service。


可以看出这个函数只有两个参数,一个是接口 class 一个是实现类 class,第一个参数 cls:它会作为 key 来使用,第二个参数 implClass:它会作为 value 来使用。

Service 使用

通过 MediatorServiceFacator 懒加载获取 service 对象,如果业务方没有注册则获取一个空的对象。


注册有 service 没有使用时是不会创建的,如果使用过则会缓存下来,下次调用则直接返回。(第一次是通过反射创建)例:


  1. 在 mediator 模块下会员 CommonService 中 定义了一个模糊查询会员的方法。



  1. 在会员模块下 common 中实现了该功能。



  1. 在会员模块下 pad 中继承了这个实现。



  1. 在其他模块 pad 下使用这个功能。



可以看到获取 Service 只要传对应接口就即可,对于使用方是不用关心实现方,在开发过程中只要先定义好接口,合作的同学就可以进入正常开发了。细心的同学可以看出,返回的数据类型也是一个接口类,为什么不直接返回一个普通 java 类呢?主要原因是通过接口方法达到双方 api 约定,例如 getName() :String 方法是通过方法名返回值达到约定效果,这样不依赖具体实现。


从上面的例子可以看出主要分为三个部分:1、定义接口。2、提供方实现接口。3、使用方都通过服务工厂获取服务使用。对于使用者来是很简单的,不需要关心实现,通过接口可以直接获取到实现,并且获取到结果可以直接使用,不需要做序列化处理。

有了路由通信我们为什么还使用面向接口编程?

路由模式虽然很好的解决了耦合的问题,但他的方法调用都是静态的,对于传参与返回值只能是基本类型,如果是对象需要做序列化与反序列化处理,对性能有一定影响。类似在调后台接口一样,同时降低了代码的可读性, 对于 app 而言所有 Module 都是在同一个应用下,没有必要做这些序列化操作。


对于复杂业务不好处理,例如一个业务需要多次通信,路由模式则不好处理,而通过接口通信则可以容易解决。例如:一个读卡的操作,业务方需要对它有开启、关闭、暂停等多个状态的操作。通过接口则可以直接返回一个读卡的 service 控制器, 这样可以直接进行相应的控制操作。



从上面代码中可以看出,上层回调结果的同时并回调了一个控制接口,这样就提供使用方一个反向操作的能力。

三、总结

通过路由通信,可以很好的解决模块间耦合,但拿不到对象无法持续交互,并且需要序列化,而通过接口通信,则很好地解决了这一点,并且代码可读性比较高。而接口通信会有一定的耦合性,也就是依赖了提供方的 service 层相当 api,但对于收益来说还是值得的方式。


在架构模式中,没有最好的模式只有比较合适自己项目的模式,希望大家都可以活学活用,谢谢。


作者介绍


本文转载自公众号有赞 coder(ID:youzan_coder)。


原文链接


https://mp.weixin.qq.com/s?__biz=MzAxOTY5MDMxNA==&mid=2455760523&idx=1&sn=9216154849b70e900f48fd5013ecf422&chksm=8c6868aebb1fe1b8b7b25833f65c12206e27be127d37eabd143332f3c489ccbf9b3e4b632d2f&scene=27#wechat_redirect


2020-02-12 10:002745

评论 1 条评论

发布
用户头像
不错,很有收获
2020-03-19 00:51
回复
没有更多了
发现更多内容

ironSource LevelPlay 聚合平台,现已适配应用开发框架工具包 Flutter

极客天地

WASM VS EVM,波卡的选择预示了公链未来

One Block Community

区块链 公链 波卡生态

如何撰写数据中台蓝图方案

agileai

数据中台 企业服务总线 主数据平台 数据分析平台 蓝图方案

英特尔计划建造浸没式实验室,帮助高功率芯片快速降温

BeeWorks

2022云原生网络趋势 | K8s托管整个基础设施、多云、边缘计算、安全等场景,将云原生网络带向新战场

York

云原生 网络 Kube-OVN cni 6月月更

java培训 | 零基础学习java开发的学习方法有哪些

@零度

Java 学习方法

【LeetCode】火柴拼正方形Java题解

Albert

LeetCode 6月月更

2022 支付宝五福 |“联机版”打年兽背后的网络技术 RTMS

阿里巴巴终端技术

客户端 网络技术 网络通信

【直播回顾】参与ArkUI,共建OpenHarmony繁荣生态

OpenHarmony开发者

Open Harmony

RxJS系列01:响应式编程与异步

代码与野兽

6月月更

2022年4月线上终端药品增长迅猛,市场政策合规进程加快

易观分析

医药类

“东数西算”与“双碳”双驱力叠加,新华三争当“全能型选手”

BeeWorks

【高并发】你知道吗?大家都在使用Redisson实现分布式锁了!!

冰河

并发编程 多线程 高并发 异步编程 6月月更

《数字经济全景白皮书》证券期货用户数字化篇 重磅发布

易观分析

证券 期货

深度操作系统20.6正式发布!

深度操作系统

开源 深度操作系统 deepin20.6 新版本 深度

运维领域告警智能定级原理探索(含详细实验报告)

云智慧AIOps社区

运维 安全 监控 告警

招聘 | 上班轰趴,下班狼人杀,天天招人,怕是要发!

Alluxio

面试 程序员人生 招聘 互联网热点 Alluxio

各国儿童节时间是不一样的

清林情报分析师

数据可视化 知识图谱 儿童节

大数据培训如何使用DPM规划用户画像

@零度

大数据 dpm

相约龙蜥,开源一“夏”!2022编程之夏ASoC开始报名了

OpenAnolis小助手

阿里巴巴 开源项目 龙蜥社区 高校学生 技术项目

为企业业务流程提速的BPM

力软低代码开发平台

为什么你的网站需要搭建在线帮助中心?

小炮

成本节省 50%,10 人团队使用函数计算开发 wolai 在线文档应用

Serverless Devs

Serverless wolai

定档615 | 数字化基础软件自主创新分享周即将来袭,点击获取“通关密钥”!

网易数帆

大数据 云原生 基础软件 数字化转型 自主创新

Docker下RabbitMQ延时队列实战两部曲之一:极速体验

程序员欣宸

RabbitMQ 5月月更 RabbtiMQ延时队列

幸运哈希算法竞猜游戏开发特点分析(成熟方案)

开发微hkkf5566

移动端异构运算技术-GPU OpenCL编程(进阶篇)

百度Geek说

做数据时代的加油站,ShardingSphere 为易车数据库架构演进提供新动力

SphereEx

Apache 数据库 开源 ShardingSphere SphereEx

6 月直播 7 场干货全剧透!今天:飞腾CPU调优原理及方法 | 第 19 期

OpenAnolis小助手

cpu 直播 sig 龙蜥大讲堂 飞腾

Jetpack Composes 入门

坚果

6月月更

CPU利用率从10%提升至60%:中型企业云原生成本优化实战指南

星汉未来

运维 云原生 IT成本 星汉未来 FinOps

Android模块化:面向接口编程_编程语言_光线_InfoQ精选文章