@startuml !theme plain skinparam classAttributeIconSize 0 skinparam defaultFontSize 12 skinparam defaultFontName Microsoft YaHei skinparam packageStyle rect skinparam backgroundColor #FFFFFF skinparam dpi 300 ' 类样式 skinparam class { BackgroundColor White ArrowColor DarkGray BorderColor Black Padding 5 FontSize 11 } ' 接口样式 skinparam interface { BackgroundColor LightBlue BorderColor SteelBlue Padding 5 FontSize 11 StereotypeFontSize 10 } ' 包样式 skinparam package { BackgroundColor WhiteSmoke BorderColor Gray Padding 10 FontSize 13 FontStyle Bold } ' 箭头样式 skinparam ArrowColor DarkSlateGray skinparam ArrowFontSize 10 skinparam ArrowThickness 1.5 skinparam Linetype ortho title 爬虫项目类图 ' 强制垂直布局,避免过宽 top to bottom direction left to right direction package "交互层" #E3F2FD { class InteractiveCLI { - running: boolean - commands: Map - persistenceManager: DataPersistenceManager + run(): void - showHelp(): void } class DataView { + displayRouteInfo(RouteInfo): void + displayWeatherInfo(WeatherInfo): void + displayAttractionInfo(List): void + displayHeader(String): void + displayError(String): void } } package "命令层" #FFF3E0 { interface Command { + execute(String[]): void } class RouteCommand { - routeService: RouteService - view: DataView - persistenceManager: DataPersistenceManager - lastRoute: RouteInfo } class WeatherCommand { - weatherService: WeatherServiceManager - view: DataView - persistenceManager: DataPersistenceManager - lastWeather: WeatherInfo } class AttractionCommand { - attractionService: AttractionService - view: DataView - persistenceManager: DataPersistenceManager - lastAttractions: List } class ExportCommand { - exporter: JsonExporter - routeSupplier: Supplier - weatherSupplier: Supplier - attractionSupplier: Supplier } class ImportCommand { - importer: JsonImporter - view: DataView } } package "服务层" #E8F5E9 { class RouteService { - apiKey: String - platform: MapPlatform + getRouteInfo(origin, dest, strategy): RouteInfo } class WeatherServiceManager { - services: List + getWeatherInfo(city): WeatherInfo } interface WeatherService { + getWeather(city): WeatherInfo } class FreeWeatherService { - baseUrl: String + getWeather(city): WeatherInfo } class AttractionService { - crawler: BaiduBaikeAttractionCrawler + searchAttractions(city): List } } package "爬虫层" #FCE4EC { class BaiduBaikeAttractionCrawler { - baseUrl: String - timeout: int + searchAttractions(city): List - parseHtml(doc, city): List } } package "策略层" #F3E5F5 { interface TransportStrategy { + getType(): String + getApiEndpoint(): String } class DrivingStrategy { + getType(): String + getApiEndpoint(): String } class BusStrategy { + getType(): String + getApiEndpoint(): String } } package "平台层" #FFF8E1 { interface MapPlatform { + getName(): String + getRouteUrl(): String + geocode(address): String } class AmapPlatform { - apiKey: String + getName(): String + getRouteUrl(): String } class BaiduPlatform { - apiKey: String + getName(): String + getRouteUrl(): String } class TencentPlatform { - apiKey: String + getName(): String + getRouteUrl(): String } } package "数据模型" #FFEBEE { class RouteInfo { - mapType: String - transportType: String - distance: double - time: double - origin: String - destination: String } class WeatherInfo { - city: String - temperature: double - feelsLike: double - weather: String - windDirection: String - windSpeed: double - humidity: int - visibility: double - updateTime: String } class AttractionInfo { - name: String - city: String - level: String - score: double - ticketPrice: double - openTime: String - address: String - description: String } } package "工具层" #ECEFF1 { class DataPersistenceManager { - objectMapper: ObjectMapper - routeData: List - weatherData: List - attractionData: List + addRouteData(route): void + addWeatherData(weather): void + addAttractionData(attraction): void + saveAllData(): void + loadSavedData(): void + getStats(): String } class JsonExporter { - mapper: ObjectMapper + exportRoute(route, from, to): void + exportWeather(weather): void + exportAttractions(attractions, city): void - generateFileName(type, name): String } class JsonImporter { - mapper: ObjectMapper + importRoute(filePath): RouteInfo + importWeather(filePath): WeatherInfo + importAttractions(filePath): List } class CityList { - CITIES: Map + selectCity(reader, prompt): String + getCoordinates(city): String } } ' ==================== 关系定义 ==================== ' 使用隐藏连线强制垂直布局顺序 InteractiveCLI -[hidden]down-> RouteCommand : "" RouteCommand -[hidden]down-> RouteService : "" RouteService -[hidden]down-> TransportStrategy : "" TransportStrategy -[hidden]down-> MapPlatform : "" MapPlatform -[hidden]down-> RouteInfo : "" RouteInfo -[hidden]down-> DataPersistenceManager : "" WeatherServiceManager -[hidden]down-> WeatherService : "" AttractionService -[hidden]down-> BaiduBaikeAttractionCrawler : "" ' 交互层关系 InteractiveCLI --> Command : 使用 InteractiveCLI --> DataView : 显示 InteractiveCLI --> DataPersistenceManager : 持久化 ' 命令实现关系 RouteCommand ..|> Command : 实现 WeatherCommand ..|> Command : 实现 AttractionCommand ..|> Command : 实现 ExportCommand ..|> Command : 实现 ImportCommand ..|> Command : 实现 ' 命令调用服务 RouteCommand --> RouteService : 调用 WeatherCommand --> WeatherServiceManager : 调用 AttractionCommand --> AttractionService : 调用 ' 服务层关系 RouteService --> TransportStrategy : 使用策略 RouteService --> MapPlatform : 使用平台 WeatherServiceManager ..> WeatherService : 管理 FreeWeatherService ..|> WeatherService : 实现 AttractionService --> BaiduBaikeAttractionCrawler : 使用爬虫 ' 策略实现关系 DrivingStrategy ..|> TransportStrategy : 实现 BusStrategy ..|> TransportStrategy : 实现 ' 平台实现关系 AmapPlatform ..|> MapPlatform : 实现 BaiduPlatform ..|> MapPlatform : 实现 TencentPlatform ..|> MapPlatform : 实现 ' 数据返回关系 RouteService ..> RouteInfo : 返回 WeatherServiceManager ..> WeatherInfo : 返回 AttractionService ..> AttractionInfo : 返回 ' 视图显示关系 DataView --> RouteInfo : 显示 DataView --> WeatherInfo : 显示 DataView --> AttractionInfo : 显示 ' 持久化关系 DataPersistenceManager --> RouteInfo : 保存 DataPersistenceManager --> WeatherInfo : 保存 DataPersistenceManager --> AttractionInfo : 保存 @enduml