Browse Source

更新 'W9/README.md'

WangYangyang 1 month ago
parent
commit
7fcf65a7b9
  1. 118
      W9/README.md

118
W9/README.md

@ -15,3 +15,121 @@ java -jar target/datacollect-cli-0.1.0-jar-with-dependencies.jar --help
项目结构(最小): 项目结构(最小):
- `src/main/java/com/example/datacollect/Main.java` — CLI 入口,打印帮助 - `src/main/java/com/example/datacollect/Main.java` — CLI 入口,打印帮助
- `pom.xml` — Maven 构建配置,生成可执行 jar - `pom.xml` — Maven 构建配置,生成可执行 jar
这是一个非常完整的 **Java CLI 应用从“可用”到“健壮”的演进过程**。我们将整个过程总结为 **5 个核心阶段**,涵盖了架构设计、代码重构、功能扩展、用户体验优化以及设计原则的落地。
---
### 整个优化流程总结
#### 1. 初始阶段:MVC + 命令模式架构搭建
**目标**:让程序跑起来,结构清晰。
* **架构**:采用 **MVC (Model-View-Controller)** 结合 **命令模式 (Command Pattern)**
* **核心类**
* `Model`: `Article` (数据实体)。
* `View`: `ConsoleView` (输入输出,颜色美化)。
* `Controller`: `CrawlerController` (命令分发)。
* `Command`: `Command` 接口 + 具体实现 (`CrawlCommand`, `ListCommand` 等)。
* **数据流**:用户输入 → Controller 解析 → 调用 Command → 操作数据 → 输出结果。
* **状态**:✅ 功能可用,✅ 结构清晰,❌ 耦合度高,❌ 扩展性差。
#### 2. 重构阶段:引入 `DataService` 解耦
**目标**:解决 `Command` 直接依赖 `List` 的问题,实现依赖倒置。
* **痛点**:原代码中 `Command` 直接持有 `List<Article>`,如果未来要存数据库或文件,所有命令都要改。
* **优化**
* 新增 `DataService` 接口(定义 `save`, `get`, `remove` 等方法)。
* 实现 `ArticleRepository` 类实现 `DataService`
* **修改 `Command` 接口**:参数从 `List<Article>` 改为 `DataService`
* **修改 `Controller`**:注入 `DataService` 而非 `List`
* **收益**:✅ **开闭原则**(新增存储方式无需改命令),✅ **易于测试**(可 Mock `DataService`)。
#### 3. 功能扩展阶段:完善 CRUD 与持久化
**目标**:让应用真正具备生产力,不仅仅是演示。
* **新增命令**
* `SearchCommand`:支持关键词搜索(查)。
* `DeleteCommand`:支持按索引删除(改)。
* `SaveCommand` / `LoadCommand`:支持文件读写(持久化)。
* **数据完整性**:确保 `CrawlCommand` 真正将数据存入 `DataService`,而非仅打印日志。
* **收益**:✅ **功能闭环**(增删改查全),✅ **数据安全**(重启不丢失)。
#### 4. 体验优化阶段:增强交互与容错
**目标**:提升用户命令行体验,减少错误操作。
* **`ListCommand` 优化**:
* 增加 `limit` 参数(如 `list 10`),防止刷屏。
* 增加分页提示(“显示前 20 条,共 50 条”)。
* 增加空列表友好提示。
* **参数校验**:所有命令增加参数数量检查(如 `crawl` 必须带 URL)。
* **异常处理**:增加 `try-catch` 处理文件 IO 异常和数字格式异常。
* **收益**:✅ **用户体验好**(防刷屏、提示清晰),✅ **健壮性强**(不轻易崩溃)。
#### 5. 最终架构:标准化与最佳实践
**目标**:形成可维护、可扩展的企业级 CLI 雏形。
* **包结构**
```text
src/
├── model/ (Article, DataService, ArticleRepository)
├── command/ (Command 接口,所有具体命令)
├── controller/ (CrawlerController)
├── view/ (ConsoleView)
└── Main.java (入口)
```
* **设计原则**
* **单一职责**:每个类只做一件事。
* **依赖倒置**:依赖接口 `DataService` 而非具体 `List`
* **开闭原则**:新增命令只需实现 `Command` 接口,无需修改 `Controller`
---
### 📊 优化前后对比表
| 维度 | 优化前 (V1) | 优化后 (V2) |
| :--- | :--- | :--- |
| **数据依赖** | `Command` 直接依赖 `List<Article>` | `Command` 依赖 `DataService` 接口 |
| **数据持久化** | ❌ 内存数据,重启丢失 | ✅ 支持 `save/load` 到文件 |
| **查询能力** | ❌ 仅能列出全部 | ✅ 支持 `search` 关键词筛选 |
| **管理能力** | ❌ 无法删除 | ✅ 支持 `delete` 按索引删除 |
| **列表显示** | ❌ 全部显示,可能刷屏 | ✅ 支持 `list <num>` 分页显示 |
| **错误处理** | ❌ 简单打印,易崩溃 | ✅ 参数校验,异常捕获 |
| **扩展性** | ❌ 新增功能需改多处 | ✅ 新增命令无需改 Controller |
---
### 🛠️ 核心代码变化速览
1. **接口定义变化**
```java
// 旧
void execute(String[] args, List<Article> articles);
// 新
void execute(String[] args, DataService dataService);
```
2. **控制器注入变化**
```java
// 旧
public CrawlerController(ConsoleView view, List<Article> articles)
// 新
public CrawlerController(ConsoleView view, DataService dataService)
```
3. **视图方法变化**
```java
// 旧
void display(List<Article> articles)
// 新
void display(List<Article> articles, int totalSize)
```
---
### 🎓 设计原则总结
在这个优化过程中,我们实际上实践了以下 **SOLID 原则**
1. **S (Single Responsibility)**:`ConsoleView` 只管显示,`DataService` 只管数据,`Command` 只管逻辑。
2. **O (Open/Closed)**:新增 `DeleteCommand` 时,不需要修改 `CrawlerController``handle` 方法。
3. **L (Liskov Substitution)**:任何实现 `DataService` 的类(如 `FileService`, `DBService`)都可以替换 `ArticleRepository`
4. **I (Interface Segregation)**:`DataService` 接口只定义了必要的数据操作方法,没有混杂 UI 逻辑。
5. **D (Dependency Inversion)**:高层模块 (`Controller`, `Command`) 依赖抽象 (`DataService`),而非具体实现 (`ArrayList`)。
---

Loading…
Cancel
Save