14 KiB
14 KiB
模块化设计
目录
模块化概念
什么是模块化?
模块化是将应用程序按照功能或职责拆分成多个独立的模块(Module),每个模块有明确的职责和接口。
模块化 vs 组件化
| 特性 | 模块化 | 组件化 |
|---|---|---|
| 粒度 | 较细,按功能拆分 | 较粗,按业务拆分 |
| 独立性 | 模块可以独立编译 | 组件可以独立运行 |
| 复用性 | 模块可以在项目内复用 | 组件可以在项目间复用 |
| 适用场景 | 中大型项目 | 大型项目、多团队协作 |
模块化架构图
┌─────────────────────────────────┐
│ App Module │
└─────────────────────────────────┘
│
┌──────┴──────┐
│ │
┌───▼───┐ ┌───▼───┐
│模块A │ │模块B │ ← 功能模块
│(Module)│ │(Module)│
└───┬───┘ └───┬───┘
│ │
└──────┬──────┘
│
┌──────▼──────┐
│ Base Module │ ← 基础模块
└──────────────┘
模块划分
1. 按功能划分
app/
├── app/ # 主应用模块
├── module_network/ # 网络模块
├── module_database/ # 数据库模块
├── module_cache/ # 缓存模块
├── module_image/ # 图片加载模块
├── module_ui/ # UI 组件模块
└── base/ # 基础模块
├── base_common/ # 公共工具
└── base_core/ # 核心功能
2. 按层次划分
app/
├── app/ # 表现层
├── domain/ # 领域层
│ ├── domain_user/ # 用户领域
│ └── domain_order/ # 订单领域
├── data/ # 数据层
│ ├── data_repository/ # 数据仓库
│ └── data_source/ # 数据源
└── base/ # 基础层
3. 按业务划分
app/
├── app/ # 主应用
├── feature_login/ # 登录功能
├── feature_home/ # 首页功能
├── feature_user/ # 用户功能
└── shared/ # 共享模块
├── shared_network/ # 网络共享
└── shared_ui/ # UI 共享
模块划分原则
- 单一职责:每个模块只负责一个功能
- 高内聚低耦合:模块内部高内聚,模块间低耦合
- 接口清晰:模块间通过接口通信
- 依赖方向:上层模块依赖下层模块
模块依赖管理
1. 依赖关系
App Module
↓
Feature Modules(功能模块)
↓
Shared Modules(共享模块)
↓
Base Module(基础模块)
2. build.gradle 配置
// app/build.gradle
dependencies {
// 依赖功能模块
implementation project(':feature_login')
implementation project(':feature_home')
implementation project(':feature_user')
// 依赖共享模块
implementation project(':shared:shared_network')
implementation project(':shared:shared_ui')
}
// feature_login/build.gradle
dependencies {
// 功能模块依赖共享模块
implementation project(':shared:shared_network')
implementation project(':shared:shared_ui')
// 功能模块依赖基础模块
implementation project(':base:base_common')
}
// shared_network/build.gradle
dependencies {
// 共享模块依赖基础模块
implementation project(':base:base_common')
}
3. 避免循环依赖
// ❌ 错误:循环依赖
// module_a 依赖 module_b
// module_b 依赖 module_a
// ✅ 正确:单向依赖
// module_a 依赖 module_b
// module_b 不依赖 module_a
4. 依赖版本管理
// 项目 build.gradle
ext {
versions = [
'compileSdk': 30,
'minSdk': 21,
'targetSdk': 30,
'kotlin': '1.5.0',
'retrofit': '2.9.0',
'okhttp': '4.9.0'
]
}
// 模块 build.gradle
android {
compileSdkVersion versions.compileSdk
defaultConfig {
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
}
}
dependencies {
implementation "com.squareup.retrofit2:retrofit:${versions.retrofit}"
implementation "com.squareup.okhttp3:okhttp:${versions.okhttp}"
}
模块间解耦
1. 接口隔离
// 定义接口
public interface INetworkModule {
<T> void request(String url, Class<T> clazz, Callback<T> callback);
}
// 模块实现接口
public class NetworkModule implements INetworkModule {
@Override
public <T> void request(String url, Class<T> clazz, Callback<T> callback) {
// 实现网络请求
}
}
// 其他模块使用接口
public class LoginModule {
private INetworkModule networkModule;
public LoginModule(INetworkModule networkModule) {
this.networkModule = networkModule;
}
public void login(String username, String password) {
networkModule.request("/login", User.class, callback);
}
}
2. 依赖注入
// 使用 Dagger2 进行依赖注入
@Module
public class NetworkModule {
@Provides
@Singleton
INetworkModule provideNetworkModule() {
return new NetworkModuleImpl();
}
}
@Module
public class LoginModule {
@Provides
LoginService provideLoginService(INetworkModule networkModule) {
return new LoginService(networkModule);
}
}
// 使用
@Component(modules = {NetworkModule.class, LoginModule.class})
public interface AppComponent {
void inject(MainActivity activity);
}
3. 事件总线
// 使用 EventBus 解耦
public class NetworkEvent {
private String eventType;
private Object data;
public NetworkEvent(String eventType, Object data) {
this.eventType = eventType;
this.data = data;
}
}
// 模块A发送事件
EventBus.getDefault().post(new NetworkEvent("login_success", user));
// 模块B接收事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onNetworkEvent(NetworkEvent event) {
if ("login_success".equals(event.getEventType())) {
// 处理登录成功事件
}
}
4. 服务发现
// 服务注册中心
public class ServiceRegistry {
private static ServiceRegistry instance;
private Map<Class, Object> services = new HashMap<>();
public static ServiceRegistry getInstance() {
if (instance == null) {
synchronized (ServiceRegistry.class) {
if (instance == null) {
instance = new ServiceRegistry();
}
}
}
return instance;
}
public <T> void register(Class<T> clazz, T service) {
services.put(clazz, service);
}
public <T> T get(Class<T> clazz) {
return (T) services.get(clazz);
}
}
// 模块注册服务
ServiceRegistry.getInstance().register(INetworkModule.class, new NetworkModuleImpl());
// 其他模块获取服务
INetworkModule networkModule = ServiceRegistry.getInstance().get(INetworkModule.class);
模块化实现
1. 项目结构
project/
├── app/ # 主应用模块
│ └── build.gradle
├── feature_login/ # 登录功能模块
│ └── build.gradle
├── feature_home/ # 首页功能模块
│ └── build.gradle
├── shared/ # 共享模块
│ ├── shared_network/ # 网络共享
│ └── shared_ui/ # UI 共享
├── base/ # 基础模块
│ ├── base_common/ # 公共工具
│ └── base_core/ # 核心功能
└── build.gradle # 项目配置
2. 模块配置
// feature_login/build.gradle
android {
compileSdkVersion 30
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
// 依赖共享模块
implementation project(':shared:shared_network')
implementation project(':shared:shared_ui')
// 依赖基础模块
implementation project(':base:base_common')
// 第三方库
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
}
3. 模块接口定义
// base_common/src/main/java/com/example/common/INetworkModule.java
public interface INetworkModule {
<T> void request(String url, Class<T> clazz, Callback<T> callback);
}
// shared_network/src/main/java/com/example/network/NetworkModuleImpl.java
public class NetworkModuleImpl implements INetworkModule {
@Override
public <T> void request(String url, Class<T> clazz, Callback<T> callback) {
// 实现网络请求
}
}
4. 模块初始化
// Application
public class MainApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 初始化基础模块
initBaseModules();
// 初始化共享模块
initSharedModules();
// 初始化功能模块
initFeatureModules();
}
private void initBaseModules() {
// 初始化基础模块
}
private void initSharedModules() {
// 注册共享模块服务
ServiceRegistry.getInstance().register(
INetworkModule.class,
new NetworkModuleImpl()
);
}
private void initFeatureModules() {
// 初始化功能模块
}
}
模块化最佳实践
1. 模块职责清晰
// ✅ 好的模块:职责单一
// network_module:只负责网络请求
public class NetworkModule {
public <T> void request(String url, Class<T> clazz, Callback<T> callback) {
// 网络请求逻辑
}
}
// ❌ 不好的模块:职责过多
// network_module:既负责网络请求,又负责数据解析、缓存等
public class NetworkModule {
public void request() { }
public void parse() { }
public void cache() { }
}
2. 接口设计
// ✅ 好的接口:职责单一,参数清晰
public interface INetworkModule {
<T> void request(String url, Class<T> clazz, Callback<T> callback);
}
// ❌ 不好的接口:职责过多,参数复杂
public interface INetworkModule {
void request();
void parse();
void cache();
void upload();
void download();
}
3. 依赖管理
// ✅ 好的依赖:清晰、单向
// feature_login → shared_network → base_common
// ❌ 不好的依赖:循环依赖
// feature_login → feature_home
// feature_home → feature_login
4. 版本管理
// ✅ 好的版本管理:统一管理
ext {
versions = [
'compileSdk': 30,
'retrofit': '2.9.0'
]
}
// ❌ 不好的版本管理:分散管理
// 每个模块单独定义版本号
5. 测试
// 每个模块可以独立测试
// network_module 测试
public class NetworkModuleTest {
@Test
public void testRequest() {
// 测试网络请求
}
}
面试常见问题
Q1: 什么是模块化?
答案: 模块化是将应用程序按照功能或职责拆分成多个独立的模块(Module),每个模块有明确的职责和接口。
Q2: 模块化和组件化的区别?
答案:
- 模块化:粒度较细,按功能拆分,模块可以独立编译
- 组件化:粒度较粗,按业务拆分,组件可以独立运行
- 适用场景:模块化适合中大型项目,组件化适合大型项目、多团队协作
Q3: 如何划分模块?
答案:
- 按功能划分:网络模块、数据库模块、缓存模块等
- 按层次划分:表现层、领域层、数据层等
- 按业务划分:登录功能、首页功能、用户功能等
- 遵循单一职责、高内聚低耦合原则
Q4: 如何管理模块依赖?
答案:
- 依赖关系:App Module → Feature Modules → Shared Modules → Base Module
- 避免循环依赖
- 统一版本管理
- 使用依赖注入
Q5: 如何实现模块间解耦?
答案:
- 接口隔离:定义接口,模块实现接口
- 依赖注入:使用 Dagger2 等框架
- 事件总线:使用 EventBus 等
- 服务发现:使用服务注册中心
Q6: 模块化的最佳实践?
答案:
- 模块职责清晰:单一职责原则
- 接口设计:职责单一,参数清晰
- 依赖管理:清晰、单向依赖
- 版本管理:统一管理版本号
- 测试:每个模块可以独立测试
总结
模块化是 Android 应用架构的重要方式,通过将应用拆分成多个独立模块,可以实现代码复用、易于维护、团队协作等优势。在实际项目中,需要合理划分模块、管理模块依赖、实现模块间解耦。
最后更新:2024年