You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
1 month ago | |
|---|---|---|
| .. | ||
| command | 1 month ago | |
| controller | 1 month ago | |
| model | 1 month ago | |
| repository | 1 month ago | |
| strategy | 1 month ago | |
| view | 1 month ago | |
| Main.java | 1 month ago | |
| README.md | 1 month ago | |
README.md
W10 作业提交:设计模式实战
目录结构
w10/
└── src/
└── main/
└── java/
└── com/
└── example/
└── datacollect/
├── Main.java
├── command/
│ ├── Command.java
│ ├── CrawlCommand.java
│ ├── AnalyzeCommand.java
│ ├── ListCommand.java
│ ├── HelpCommand.java
│ ├── ExitCommand.java
│ └── HistoryCommand.java
├── controller/
│ └── CrawlerController.java
├── model/
│ └── Article.java
├── repository/
│ └── ArticleRepository.java
├── strategy/
│ ├── CrawlStrategy.java
│ ├── StrategyFactory.java
│ ├── HnuNewsStrategy.java
│ ├── BlogStrategy.java
│ ├── NewsStrategy.java
│ └── GenericNewsStrategy.java
└── view/
└── ConsoleView.java
必做任务完成情况
1. ArticleRepository 完善 ✅
add(): 拒绝 null,抛出 IllegalArgumentExceptionaddAll(): 拒绝 null 列表和列表中的 null 元素getAll(): 返回Collections.unmodifiableList()不可变视图size(): 返回文章数量clear(): 清空所有文章
2. AnalyzeCommand ✅
- 复用策略解析但不存储到 Repository
- 输出统计信息:文章总数、含作者/日期/内容的数量、使用的策略名称
- 显示前 3 篇文章标题作为预览
3. AI 架构审计 ✅
类签名汇总
// Command 层
interface Command { void execute(String[], ArticleRepository); }
class CrawlCommand(ConsoleView, StrategyFactory)
class AnalyzeCommand(ConsoleView, StrategyFactory)
class ListCommand(ConsoleView)
class HelpCommand(ConsoleView)
class ExitCommand(ConsoleView)
class HistoryCommand(ConsoleView, List<String>)
// Controller 层
class CrawlerController(ConsoleView, ArticleRepository, StrategyFactory)
// Repository 层
class ArticleRepository { add(), addAll(), getAll(), size(), clear() }
// Strategy 层
interface CrawlStrategy { parse(), supports(), getPriority(), getPattern() }
class StrategyFactory { getStrategy(url), register(), setDefaultStrategy() }
class HnuNewsStrategy implements CrawlStrategy
class BlogStrategy implements CrawlStrategy
class NewsStrategy implements CrawlStrategy
class GenericNewsStrategy implements CrawlStrategy (正则匹配)
// Model 层
class Article { title, url, content, author, publishDate }
// View 层
class ConsoleView
架构审计结果
| 检查项 | 结果 | 说明 |
|---|---|---|
| 策略解耦 | ✅ 优秀 | 策略接口与实现完全分离 |
| Repository 封装 | ✅ 优秀 | 使用不可变视图 + null 防御 |
| 开闭原则 | ✅ 达标 | 新增网站只需加策略类 + 注册一行 |
| 依赖倒置 | ✅ 良好 | Command/Strategy 依赖抽象接口 |
| 单一职责 | ✅ 达标 | 每个类职责清晰 |
| 循环依赖 | ✅ 无 | 依赖链单向 |
选做任务完成情况
正则策略匹配 ✅
GenericNewsStrategy使用正则表达式.*\.(news|press|article)s?\..*匹配新闻类网站
默认策略 ✅
StrategyFactory内置DefaultStrategy,当没有匹配策略时返回空列表
策略优先级 ✅
CrawlStrategy接口新增getPriority()默认方法GenericNewsStrategy设置优先级为 5(高于默认优先级 1)StrategyFactory.getStrategy()遍历所有策略,选择优先级最高的匹配策略
思考题答案
Q: 两个策略都 supports 同一 URL 时怎么办?
A: 采用优先级机制解决:
- 每个策略实现可以通过
getPriority()返回优先级值 StrategyFactory.getStrategy()遍历所有策略时,记录最高优先级- 如果多个策略都支持同一 URL,选择优先级最高的那个
- 如果优先级相同,选择最先注册的策略(遍历顺序决定)
这种设计的优势:
- 允许通用策略(如
GenericNewsStrategy)和专用策略(如HnuNewsStrategy)共存 - 专用策略可设置更高优先级,确保精确匹配优先
- 通用策略作为兜底,提高系统兼容性
命令功能对比
| 命令 | 功能 | 是否存储 |
|---|---|---|
crawl <url> |
爬取并存储文章 | ✅ 是 |
analyze <url> |
分析文章统计(不存储) | ❌ 否 |
list |
列出已存储文章 | - |
history |
显示命令历史 | - |
help |
显示帮助 | - |
exit |
退出程序 | - |
设计模式应用
- 策略模式:
CrawlStrategy接口定义标准,各策略独立实现 - 工厂模式:
StrategyFactory根据 URL 自动选择策略 - Repository 模式:数据访问封装,防御式编程
- 命令模式:所有 Command 统一签名,易于扩展