项目结构:

rust
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : process_dtos.rs
//! DTO(数据传输对象)定义
//!
//! 用于跨层(表现层 → 接口层 → 应用层 → 领域层)传递数据,仅承载数据、无业务逻辑。
//! - `ProcessRequestDto`:业务流程执行请求
//! - `ProcessResponseDto`:业务流程执行响应
use crate::domain::entities::jewelry::Jewelry;
/// 业务流程执行请求 DTO
///
/// `department` / `operator` 为溯源扩展字段(预留给审计场景),
/// 当前演示中同事自行声明所属部门,未读取该两字段。
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ProcessRequestDto {
/// 流程类型标识(如 PROCUREMENT / DESIGN / PRODUCTION 等)
pub process_type: String,
/// 关联珠宝实体
pub jewelry: Jewelry,
/// 发起部门(如 采购部 / 设计部 / 生产部 等)
pub department: String,
/// 操作人(如 Mediator 中介者 / 具体岗位名称)
pub operator: String,
}
impl ProcessRequestDto {
/// 创建业务流程执行请求 DTO
///
/// # 参数
/// - `process_type`:流程类型标识
/// - `jewelry`:关联珠宝
/// - `department`:发起部门
/// - `operator`:操作人
///
/// # 返回
/// 请求 DTO
pub fn new(process_type: &str, jewelry: Jewelry, department: &str, operator: &str) -> Self {
Self {
process_type: process_type.to_string(),
jewelry,
department: department.to_string(),
operator: operator.to_string(),
}
}
}
/// 业务流程执行响应 DTO
///
/// `instance_id` 预留给需要回传实例编号的上层调用方,演示中编号已写入日志。
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ProcessResponseDto {
/// 流程实例编号(如 PROCUREMENT-000001)
pub instance_id: String,
/// 流程名称(中文)
pub process_name: String,
/// 是否成功
pub success: bool,
/// 结果消息(成功摘要或失败原因)
pub message: String,
}
impl ProcessResponseDto {
/// 创建流程响应 DTO
///
/// # 参数
/// - `instance_id`:流程实例编号
/// - `process_name`:流程名称
/// - `success`:是否成功
/// - `message`:结果消息
///
/// # 返回
/// 响应 DTO
pub fn new(instance_id: &str, process_name: &str, success: bool, message: &str) -> Self {
Self {
instance_id: instance_id.to_string(),
process_name: process_name.to_string(),
success,
message: message.to_string(),
}
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : jewelry.rs
//! 珠宝行业领域实体定义
//!
//! 包含:
//! - `Jewelry`:珠宝业务实体(贯穿采购→设计→生产→质检→包装→物流→财务→
//! 营销→销售等全部流程)
//! - `ProcessOutcome`:业务流程执行产出(同事业务执行的返回载体)
//! - 全局自增流水号生成器(线程安全,用于生成唯一编号)
use std::sync::atomic::{AtomicU64, Ordering};
/// 全局自增流水号(线程安全,跨线程共享生成唯一序号)
static NEXT_SEQUENCE: AtomicU64 = AtomicU64::new(1);
/// 获取下一个业务流水号(原子递增,高并发安全)
///
/// # 返回
/// 下一个自增序号
pub fn next_sequence() -> u64 {
NEXT_SEQUENCE.fetch_add(1, Ordering::SeqCst)
}
/// 珠宝业务实体(领域实体,跨全流程共享)
///
/// `id` / `status` / `with_status` 为领域状态演进预留(如 `PROCURED`→`DELIVERED`),
/// 当前演示以值传递共享珠宝实体,未对状态字段做持久化演进,属预留 API。
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct Jewelry {
/// 珠宝编号(如 JWL-000001)
pub id: String,
/// 珠宝名称
pub name: String,
/// 材质(黄金 / 铂金 / 钻石 / K金 / 银)
pub material: String,
/// 重量(克)
pub weight_grams: f64,
/// 零售价(元)
pub price: f64,
/// 当前状态(INIT 初始 / PROCURED 已采购 / DESIGNED 已设计 /
/// PRODUCED 已生产 / INSPECTED 已质检 / PACKED 已包装 / DELIVERED 已发货)
pub status: String,
}
impl Jewelry {
/// 创建珠宝实体
///
/// # 参数
/// - `name`:珠宝名称
/// - `material`:材质
/// - `weight_grams`:重量(克)
/// - `price`:零售价(元)
///
/// # 返回
/// 初始状态为 `INIT` 的珠宝实体
pub fn new(name: &str, material: &str, weight_grams: f64, price: f64) -> Self {
Self {
id: format!("JWL-{:06}", next_sequence()),
name: name.to_string(),
material: material.to_string(),
weight_grams,
price,
status: "INIT".to_string(),
}
}
/// 更新珠宝状态(返回新实体,保持不可变语义便于并发共享)
///
/// # 参数
/// - `status`:新状态
///
/// # 返回
/// 更新状态后的珠宝实体副本
#[allow(dead_code)]
pub fn with_status(&self, status: &str) -> Self {
let mut cloned = self.clone();
cloned.status = status.to_string();
cloned
}
}
/// 业务流程执行产出(同事业务执行的返回载体)
///
/// `instance_id` 预留给产出追溯使用,当前已写入执行记录(`ProcessRecord`),
/// 此处字段作为冗余追溯标识保留。
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ProcessOutcome {
/// 流程实例编号
pub instance_id: String,
/// 产出摘要(中文描述)
pub summary: String,
/// 是否成功
pub success: bool,
}
impl ProcessOutcome {
/// 创建成功产出
///
/// # 参数
/// - `instance_id`:流程实例编号
/// - `summary`:产出摘要
///
/// # 返回
/// 成功产出
pub fn success(instance_id: &str, summary: &str) -> Self {
Self {
instance_id: instance_id.to_string(),
summary: summary.to_string(),
success: true,
}
}
/// 创建失败产出
///
/// 预留 API:当前演示业务执行失败时直接返回错误,不构造失败产出;
/// 该构造器预留给需要显式失败产出的场景。
///
/// # 参数
/// - `instance_id`:流程实例编号
/// - `summary`:产出摘要
///
/// # 返回
/// 失败产出
#[allow(dead_code)]
pub fn failure(instance_id: &str, summary: &str) -> Self {
Self {
instance_id: instance_id.to_string(),
summary: summary.to_string(),
success: false,
}
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : colleague.rs
//! 中介者模式核心:Colleague(同事)抽象
//!
//! 同事是参与协同的业务部门。核心约束:**同事之间不直接相互引用**,
//! 而是通过注入的中介者(`Arc<dyn BusinessMediator>`)通信------
//! 执行业务后可向中介者广播事件、查询其他部门产出。
use std::sync::Arc;
use std::sync::Mutex;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::{BusinessEvent, BusinessMediator};
/// 同事共享支持(中介者引用存储 + 日志),供各具体同事组合复用
pub struct ColleagueSupport {
/// 统一日志对象(依赖注入)
logger: Arc<dyn Logger>,
/// 中介者引用(由中介者注册时注入,受互斥锁保护,线程安全)
mediator: Mutex<Option<Arc<dyn BusinessMediator>>>,
}
impl ColleagueSupport {
/// 创建同事共享支持
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事支持实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
logger,
mediator: Mutex::new(None),
}
}
/// 注入中介者
///
/// # 参数
/// - `mediator`:中介者实例
pub fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
*self.mediator.lock().unwrap() = Some(mediator);
}
/// 获取中介者(可能尚未注入)
///
/// # 返回
/// 中介者实例(可能为空)
pub fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.mediator.lock().unwrap().clone()
}
/// 获取统一日志对象
///
/// # 返回
/// 统一日志对象引用
pub fn logger(&self) -> &Arc<dyn Logger> {
&self.logger
}
}
/// 同事抽象(Colleague trait,线程安全)
///
/// 约束 `Send + Sync`,保证可经 `Arc<dyn Colleague>` 注入中介者,
/// 并在多线程高并发环境下共享执行。
pub trait Colleague: Send + Sync {
/// 获取同事标识(如 PROCUREMENT)
///
/// # 返回
/// 同事标识
fn colleague_id(&self) -> &'static str;
/// 获取同事名称(中文,如 原料采购核验)
///
/// # 返回
/// 同事名称
fn colleague_name(&self) -> &'static str;
/// 获取所属部门(如 采购部)
///
/// # 返回
/// 部门名称
fn department(&self) -> &'static str;
/// 获取统一日志对象(由依赖注入提供)
///
/// # 返回
/// 统一日志对象引用
fn logger(&self) -> &Arc<dyn Logger>;
/// 注入中介者(由中介者注册时调用)
///
/// # 参数
/// - `mediator`:中介者实例
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>);
/// 获取注入的中介者(可能为空)
///
/// # 返回
/// 中介者实例(可能为空)
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>>;
/// **执行业务动作**(同事核心业务,子类必须实现)
///
/// # 参数
/// - `ctx`:命令上下文
///
/// # 返回
/// - `Ok(ProcessOutcome)`:业务成功产出
/// - `Err(ProcessError)`:业务失败
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError>;
/// 响应中介者转发的业务事件(默认空实现,子类可按需覆盖)
///
/// 用于体现同事间经中介者的间接协同。
///
/// # 参数
/// - `event`:业务事件
/// - `ctx`:命令上下文
///
/// # 返回
/// - `Ok(())`:响应成功
/// - `Err(ProcessError)`:响应失败
fn on_event(&self, _event: BusinessEvent, _ctx: &CommandContext) -> Result<(), ProcessError> {
Ok(())
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : command_ctx.rs
//! 命令上下文定义
//!
//! 定义中介者模式中同事执行所需的上下文(`CommandContext`),
//! 承载一次业务执行所需的实例编号与请求 DTO。
use crate::domain::dtos::process_dtos::ProcessRequestDto;
use crate::domain::entities::jewelry::Jewelry;
/// 命令执行上下文(一次同事业务执行所需的输入与实例编号)
#[derive(Debug, Clone)]
pub struct CommandContext {
/// 流程实例编号(唯一,如 PROCUREMENT-000001)
pub instance_id: String,
/// 请求 DTO
pub request: ProcessRequestDto,
}
impl CommandContext {
/// 创建命令上下文
///
/// # 参数
/// - `instance_id`:流程实例编号
/// - `request`:请求 DTO
///
/// # 返回
/// 命令上下文
pub fn new(instance_id: &str, request: ProcessRequestDto) -> Self {
Self {
instance_id: instance_id.to_string(),
request,
}
}
/// 获取关联珠宝实体
///
/// # 返回
/// 珠宝实体引用
pub fn jewelry(&self) -> &Jewelry {
&self.request.jewelry
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : mediator.rs
//! 中介者模式核心:Mediator(中介者)抽象
//!
//! 中介者封装一组对象(同事)之间的交互,集中管理:
//! - 同事注册表
//! - 部门产出查询/记录(同事通过中介者间接获取其他部门产出)
//! - 业务事件路由(dispatch:把某部门完成的事件转发给相关部门)
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::Colleague;
use crate::domain::mediator::command_ctx::CommandContext;
/// 业务事件(部门完成后的业务事件,供中介者路由协调)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BusinessEvent {
/// 原料采购核验完成
ProcurementCompleted,
/// 设计制图完成
DesignCompleted,
/// 加工生产完成
ProductionCompleted,
/// 质检完成
InspectionCompleted,
/// 包装完成
PackagingCompleted,
/// 物流发货完成
LogisticsCompleted,
/// 财务核算完成
FinanceCompleted,
/// 营销推广完成
MarketingCompleted,
/// 业务销售完成
SalesCompleted,
/// 人事行政完成
HrAdminCompleted,
/// IT 完成
ItCompleted,
/// 培训完成
TrainingCompleted,
}
impl BusinessEvent {
/// 由同事标识获取其完成事件
///
/// # 参数
/// - `colleague_id`:同事标识(如 PROCUREMENT)
///
/// # 返回
/// 对应完成事件
pub fn from_colleague(colleague_id: &str) -> BusinessEvent {
match colleague_id {
"PROCUREMENT" => BusinessEvent::ProcurementCompleted,
"DESIGN" => BusinessEvent::DesignCompleted,
"PRODUCTION" => BusinessEvent::ProductionCompleted,
"INSPECTION" => BusinessEvent::InspectionCompleted,
"PACKAGING" => BusinessEvent::PackagingCompleted,
"LOGISTICS" => BusinessEvent::LogisticsCompleted,
"FINANCE" => BusinessEvent::FinanceCompleted,
"MARKETING" => BusinessEvent::MarketingCompleted,
"SALES" => BusinessEvent::SalesCompleted,
"HR_ADMIN" => BusinessEvent::HrAdminCompleted,
"IT" => BusinessEvent::ItCompleted,
"TRAINING" => BusinessEvent::TrainingCompleted,
_ => BusinessEvent::TrainingCompleted,
}
}
/// 获取事件标签(用于日志输出)
///
/// # 返回
/// 事件标签字符串
pub fn tag(&self) -> &'static str {
match self {
BusinessEvent::ProcurementCompleted => "采购完成",
BusinessEvent::DesignCompleted => "设计完成",
BusinessEvent::ProductionCompleted => "生产完成",
BusinessEvent::InspectionCompleted => "质检完成",
BusinessEvent::PackagingCompleted => "包装完成",
BusinessEvent::LogisticsCompleted => "物流完成",
BusinessEvent::FinanceCompleted => "财务完成",
BusinessEvent::MarketingCompleted => "营销完成",
BusinessEvent::SalesCompleted => "销售完成",
BusinessEvent::HrAdminCompleted => "人事完成",
BusinessEvent::ItCompleted => "IT完成",
BusinessEvent::TrainingCompleted => "培训完成",
}
}
}
/// 中介者抽象(Mediator trait,线程安全)
///
/// 约束 `Send + Sync`,保证可经 `Arc<dyn BusinessMediator>` 注入到多个同事,
/// 并在多线程高并发环境下共享协调。
pub trait BusinessMediator: Send + Sync {
/// 注册同事
///
/// # 参数
/// - `colleague`:同事实例
fn register(&self, colleague: Arc<dyn Colleague>);
/// 按标识查找同事
///
/// # 参数
/// - `colleague_id`:同事标识
///
/// # 返回
/// 找到的同事实例(可能为空)
fn colleague(&self, colleague_id: &str) -> Option<Arc<dyn Colleague>>;
/// 获取全部已注册同事
///
/// # 返回
/// 全部同事实例
fn colleagues(&self) -> Vec<Arc<dyn Colleague>>;
/// 记录某部门的业务产出(供其他部门经中介者查询)
///
/// # 参数
/// - `colleague_id`:部门标识
/// - `outcome`:业务产出
fn record(&self, colleague_id: &str, outcome: ProcessOutcome);
/// 查询某部门的业务产出(同事经中介者间接获取其他部门产出)
///
/// # 参数
/// - `colleague_id`:部门标识
///
/// # 返回
/// 该部门产出(可能为空)
fn query(&self, colleague_id: &str) -> Option<ProcessOutcome>;
/// 分发业务事件给相关同事(中介者集中管理部门间交互)
///
/// # 参数
/// - `sender_id`:发送事件的部门标识
/// - `event`:业务事件
/// - `ctx`:命令上下文
///
/// # 返回
/// - `Ok(())`:分发完成
/// - `Err(ProcessError)`:分发失败
fn dispatch(
&self,
sender_id: &str,
event: BusinessEvent,
ctx: &CommandContext,
) -> Result<(), ProcessError>;
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : process_repository.rs
//! 业务流程仓储接口(领域层抽象,由基础设施层实现)
//!
//! 仓储用于持久化每次同事业务执行的记录,供统计与追溯使用。
//! 领域层只定义接口,具体存储(内存 / 数据库)由基础设施层按 DI 注入。
use crate::common::error::ProcessError;
use crate::domain::entities::jewelry::ProcessOutcome;
/// 业务流程执行记录(持久化载体)
#[derive(Debug, Clone)]
pub struct ProcessRecord {
/// 流程实例编号
pub instance_id: String,
/// 流程名称(中文)
pub process_name: String,
/// 执行产出
pub outcome: ProcessOutcome,
/// 执行时间(格式:YYYY-MM-DD HH:MM:SS)
pub executed_at: String,
}
/// 业务流程仓储抽象接口(线程安全)
pub trait ProcessRepository: Send + Sync {
/// 保存业务执行记录
///
/// # 参数
/// - `record`:执行记录
///
/// # 返回
/// - `Ok(())`:保存成功
/// - `Err(ProcessError)`:保存失败
fn save(&self, record: ProcessRecord) -> Result<(), ProcessError>;
/// 查询全部执行记录
///
/// # 返回
/// 全部执行记录
fn find_all(&self) -> Vec<ProcessRecord>;
/// 统计成功/失败数量
///
/// # 返回
/// `(成功数量, 失败数量)` 元组
fn count(&self) -> (usize, usize);
}
rust
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : container.rs
//! 依赖注入容器(组合根 Composition Root)
//!
//! 职责:集中装配(new)全部依赖并暴露访问方法,实现构造器注入。
//! - 统一日志(`Arc<dyn Logger>`)单例
//! - 重试 + 熔断适配器单例(`Arc<RetryCircuitBreaker>`)
//! - 具体中介者(`ConcreteMediator`)单例
//! - 12 个同事(Colleague 子类)注册到中介者
//! - 内存仓储单例
//! - 业务流程应用服务
//!
//! 依赖方向严格单向:presentation → interface → application → domain → common,
//! 基础设施层向上提供实现,由容器完成组装。
use std::sync::Arc;
use std::time::Duration;
use crate::application::colleagues::business_sales::BusinessSalesColleague;
use crate::application::colleagues::design::DesignColleague;
use crate::application::colleagues::finance::FinanceColleague;
use crate::application::colleagues::hr_admin::HrAdminColleague;
use crate::application::colleagues::inspection::InspectionColleague;
use crate::application::colleagues::it::ItColleague;
use crate::application::colleagues::logistics::LogisticsColleague;
use crate::application::colleagues::marketing::MarketingColleague;
use crate::application::colleagues::packaging::PackagingColleague;
use crate::application::colleagues::procurement::ProcurementColleague;
use crate::application::colleagues::production::ProductionColleague;
use crate::application::colleagues::training::TrainingColleague;
use crate::application::mediator::concrete_mediator::ConcreteMediator;
use crate::application::services::process_service::ProcessService;
use crate::common::logging::Logger;
use crate::common::resilience::retry_circuit_breaker::RetryCircuitBreaker;
use crate::domain::mediator::colleague::Colleague;
use crate::domain::mediator::mediator::BusinessMediator;
use crate::infrastructure::logging::file_logger::FileLogger;
use crate::infrastructure::persistence::memory_process_repository::MemoryProcessRepository;
/// 依赖注入容器(组合根)
pub struct ServiceContainer {
/// 统一日志(单例)
logger: Arc<dyn Logger>,
/// 重试 + 熔断适配器(单例,预留给扩展组件复用)
#[allow(dead_code)]
resilience: Arc<RetryCircuitBreaker>,
/// 具体中介者(单例,由应用服务内部使用;此处持有以便装配与扩展)
#[allow(dead_code)]
mediator: Arc<ConcreteMediator>,
/// 内存仓储(单例,预留给扩展组件复用)
#[allow(dead_code)]
repository: Arc<MemoryProcessRepository>,
/// 业务流程应用服务
service: Arc<ProcessService>,
}
impl ServiceContainer {
/// 构建依赖注入容器(组合根,统一装配全部服务与同事)
///
/// # 返回
/// 已装配完成的容器实例
pub fn new() -> Self {
// 1. 基础设施依赖(单例)
let logger: Arc<dyn Logger> = Arc::new(FileLogger::new("./Logs"));
// 重试 2 次、连续失败 3 次熔断、冷却 5 秒
let resilience = Arc::new(RetryCircuitBreaker::new(2, 3, Duration::from_secs(5)));
let repository = Arc::new(MemoryProcessRepository::new());
// 2. 创建具体中介者(注入统一日志 + 重试熔断适配器)
let mediator = Arc::new(ConcreteMediator::new(logger.clone(), resilience.clone()));
// 3. 创建 12 个同事并注入中介者引用
let colleagues: Vec<Arc<dyn Colleague>> = vec![
Arc::new(ProcurementColleague::new(logger.clone())),
Arc::new(DesignColleague::new(logger.clone())),
Arc::new(ProductionColleague::new(logger.clone())),
Arc::new(InspectionColleague::new(logger.clone())),
Arc::new(PackagingColleague::new(logger.clone())),
Arc::new(LogisticsColleague::new(logger.clone())),
Arc::new(FinanceColleague::new(logger.clone())),
Arc::new(MarketingColleague::new(logger.clone())),
Arc::new(BusinessSalesColleague::new(logger.clone())),
Arc::new(HrAdminColleague::new(logger.clone())),
Arc::new(ItColleague::new(logger.clone())),
Arc::new(TrainingColleague::new(logger.clone())),
];
// 为每个同事注入中介者引用(构造器注入 + 中介者注册)
for colleague in &colleagues {
colleague.set_mediator(mediator.clone());
mediator.register(colleague.clone());
}
// 4. 应用层服务(构造器注入)
let service = Arc::new(ProcessService::new(
mediator.clone(),
repository.clone(),
logger.clone(),
));
Self {
logger,
resilience,
mediator,
repository,
service,
}
}
/// 获取业务流程应用服务
///
/// # 返回
/// 应用服务(`Arc` 共享)
pub fn service(&self) -> Arc<ProcessService> {
self.service.clone()
}
/// 获取具体中介者
///
/// # 返回
/// 中介者(`Arc` 共享)
#[allow(dead_code)]
pub fn mediator(&self) -> Arc<ConcreteMediator> {
self.mediator.clone()
}
/// 获取统一日志对象
///
/// # 返回
/// 统一日志(`Arc<dyn Logger>`)
pub fn logger(&self) -> Arc<dyn Logger> {
self.logger.clone()
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : file_logger.rs
//! 文件日志实现(按日期分文件夹、按日志等级分文件)
//!
//! 目录结构(示例,日期为当日):
//! ```text
//! Logs/
//! 2026-07-06/
//! app-info.log
//! app-error.log
//! app-debug.log
//! app-warn.log
//! ```
//!
//! 设计要点:
//! - **线程安全 / 高并发**:每个日志等级使用独立的 `Mutex<BufWriter<File>>`,
//! 同一等级写操作串行化,不同等级互不阻塞;可被 `Arc` 共享到多线程。
//! - **日期滚动**:每次写入检测日期目录,跨天自动切换到新的日期文件夹。
//! - **控制台与文件一致**:统一格式化 `[时间] [等级] 消息`,
//! 同时输出到控制台(stdout/stderr)与对应文件。
use std::fs::{self, File, OpenOptions};
use std::io::Write;
use std::path::PathBuf;
use std::sync::Mutex;
use crate::common::logging::{LogLevel, Logger};
/// 单日志等级的文件写入句柄(受互斥锁保护)
struct LevelWriter {
/// 当前打开的缓冲写入器
writer: Option<std::io::BufWriter<File>>,
/// 该句柄对应的日期文件夹(用于跨天滚动判断)
opened_date: String,
}
impl LevelWriter {
/// 创建空的等级写入器
fn new() -> Self {
Self {
writer: None,
opened_date: String::new(),
}
}
}
/// 文件日志实现(线程安全、支持高并发写入)
pub struct FileLogger {
/// 日志根目录(默认 ./Logs)
base_dir: PathBuf,
/// 调试日志写入器
debug_writer: Mutex<LevelWriter>,
/// 信息日志写入器
info_writer: Mutex<LevelWriter>,
/// 警告日志写入器
warn_writer: Mutex<LevelWriter>,
/// 错误日志写入器
error_writer: Mutex<LevelWriter>,
}
impl FileLogger {
/// 创建文件日志
///
/// # 参数
/// - `base_dir`:日志根目录(如 "./Logs")
///
/// # 返回
/// 文件日志实例
pub fn new(base_dir: &str) -> Self {
Self {
base_dir: PathBuf::from(base_dir),
debug_writer: Mutex::new(LevelWriter::new()),
info_writer: Mutex::new(LevelWriter::new()),
warn_writer: Mutex::new(LevelWriter::new()),
error_writer: Mutex::new(LevelWriter::new()),
}
}
/// 获取当前日期文件夹名(如 2026-07-06)
///
/// # 返回
/// 日期字符串
fn date_folder(&self) -> String {
chrono::Local::now().format("%Y-%m-%d").to_string()
}
/// 确保日期目录存在并返回目录路径
///
/// # 参数
/// - `date_folder`:日期文件夹名
///
/// # 返回
/// 日期目录路径
fn ensure_dir(&self, date_folder: &str) -> PathBuf {
let dir = self.base_dir.join(date_folder);
let _ = fs::create_dir_all(&dir);
dir
}
/// 以追加模式打开指定等级日志文件(返回缓冲写入器)
///
/// # 参数
/// - `level`:日志等级
///
/// # 返回
/// 缓冲写入器
fn open_writer(&self, level: LogLevel) -> std::io::BufWriter<File> {
let date_folder = self.date_folder();
let dir = self.ensure_dir(&date_folder);
let path = dir.join(level.file_name());
let file = OpenOptions::new()
.create(true)
.append(true)
.open(&path)
.unwrap_or_else(|e| panic!("无法打开日志文件 {}:{}", path.display(), e));
std::io::BufWriter::new(file)
}
/// 写入日志(统一格式;控制台与文件同时输出)
///
/// # 参数
/// - `level`:日志等级
/// - `message`:日志消息
fn write(&self, level: LogLevel, message: &str) {
let timestamp = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
let line = format!("[{}] [{}] {}", timestamp, level.tag(), message);
// ① 输出到控制台(错误走 stderr,其余走 stdout)
match level {
LogLevel::Error => eprintln!("{}", line),
_ => println!("{}", line),
}
// ② 输出到文件(按等级互斥锁串行化,保证线程安全)
let target = match level {
LogLevel::Debug => &self.debug_writer,
LogLevel::Info => &self.info_writer,
LogLevel::Warn => &self.warn_writer,
LogLevel::Error => &self.error_writer,
};
let mut guard = target.lock().unwrap();
let date_folder = self.date_folder();
// 跨天或未打开 → 重新打开文件(实现按日期滚动)
if guard.opened_date != date_folder || guard.writer.is_none() {
guard.opened_date = date_folder.clone();
guard.writer = Some(self.open_writer(level));
}
if let Some(writer) = guard.writer.as_mut() {
let _ = writeln!(writer, "{}", line);
let _ = writer.flush();
}
}
}
/// 实现统一日志接口(`Arc<dyn Logger>` 可注入各组件)
impl Logger for FileLogger {
/// 输出调试日志
fn debug(&self, message: &str) {
self.write(LogLevel::Debug, message);
}
/// 输出信息日志
fn info(&self, message: &str) {
self.write(LogLevel::Info, message);
}
/// 输出警告日志
fn warn(&self, message: &str) {
self.write(LogLevel::Warn, message);
}
/// 输出错误日志
fn error(&self, message: &str) {
self.write(LogLevel::Error, message);
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : memory_process_repository.rs
//! 内存仓储实现(线程安全)
//!
//! 以 `Mutex<HashMap>` 实现 `ProcessRepository` 接口,供业务执行记录
//! 的保存、查询与统计使用。演示场景使用内存存储;生产环境可替换为数据库实现。
use std::collections::HashMap;
use std::sync::Mutex;
use crate::common::error::ProcessError;
use crate::domain::repository::process_repository::{ProcessRecord, ProcessRepository};
/// 内存仓储实现
pub struct MemoryProcessRepository {
/// 内部存储(以流程实例编号为键,受互斥锁保护,保证并发安全)
store: Mutex<HashMap<String, ProcessRecord>>,
}
impl MemoryProcessRepository {
/// 创建内存仓储
///
/// # 返回
/// 内存仓储实例
pub fn new() -> Self {
Self {
store: Mutex::new(HashMap::new()),
}
}
}
impl ProcessRepository for MemoryProcessRepository {
/// 保存业务执行记录
///
/// # 参数
/// - `record`:执行记录
///
/// # 返回
/// - `Ok(())`:保存成功
/// - `Err(ProcessError)`:保存失败
fn save(&self, record: ProcessRecord) -> Result<(), ProcessError> {
let mut store = self.store.lock().unwrap();
store.insert(record.instance_id.clone(), record);
Ok(())
}
/// 查询全部执行记录
///
/// # 返回
/// 全部执行记录
fn find_all(&self) -> Vec<ProcessRecord> {
let store = self.store.lock().unwrap();
store.values().cloned().collect()
}
/// 统计成功/失败数量
///
/// # 返回
/// `(成功数量, 失败数量)` 元组
fn count(&self) -> (usize, usize) {
let store = self.store.lock().unwrap();
let total = store.values().len();
let success = store.values().filter(|r| r.outcome.success).count();
(success, total - success)
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : contracts.rs
//! 对外交互契约(Contracts)
//!
//! 定义外部调用方与系统交互的统一契约结构(业务信封),
//! 承载「部门标识 + 执行请求」,供表现层/外部系统装配。
use crate::domain::dtos::process_dtos::ProcessRequestDto;
/// 业务信封(外部提交一个部门业务的载体)
#[derive(Debug, Clone)]
pub struct BusinessEnvelope {
/// 部门/同事标识(如 PROCUREMENT)
pub colleague_id: String,
/// 执行请求 DTO
pub request: ProcessRequestDto,
}
impl BusinessEnvelope {
/// 创建业务信封
///
/// # 参数
/// - `colleague_id`:部门/同事标识
/// - `request`:执行请求
///
/// # 返回
/// 业务信封
pub fn new(colleague_id: &str, request: ProcessRequestDto) -> Self {
Self {
colleague_id: colleague_id.to_string(),
request,
}
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : ports.rs
//! 对外 API 端口契约(Ports)
//!
//! 定义表现层(presentation)与外部调用方可消费的应用端口,
//! 将「应用能力」与「具体实现」解耦;具体实现由表现层/应用层提供。
use crate::common::error::ProcessError;
use crate::domain::dtos::process_dtos::{ProcessRequestDto, ProcessResponseDto};
use crate::domain::repository::process_repository::ProcessRecord;
/// 对外应用 API 端口契约(线程安全)
///
/// 表现层实现该端口并向外部暴露;外部仅依赖本端口,不依赖具体实现。
pub trait BusinessApiPort: Send + Sync {
/// 派发并执行单个部门业务(经中介者)
///
/// # 参数
/// - `colleague_id`:同事标识(如 PROCUREMENT)
/// - `request`:执行请求 DTO
///
/// # 返回
/// - `Ok(ProcessResponseDto)`:执行响应
/// - `Err(ProcessError)`:执行失败
fn dispatch(
&self,
colleague_id: &str,
request: ProcessRequestDto,
) -> Result<ProcessResponseDto, ProcessError>;
/// 获取业务执行统计(成功数量,失败数量)
///
/// # 返回
/// `(成功数量, 失败数量)` 元组
fn statistics(&self) -> (usize, usize);
/// 获取全部业务执行记录(用于追溯/汇总展示)
///
/// # 返回
/// 全部执行记录
fn records(&self) -> Vec<ProcessRecord>;
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : mod.rs
//! 应用控制器(表现层,控制台入口)
//!
//! 职责:
//! - 从组合根(DI 容器)获取应用服务与统一日志
//! - 实现 `interface::ports::BusinessApiPort` 端口契约(对外 API)
//! - 创建贯穿全流程的珠宝实体,驱动中介者顺序协调与并发调度演示
//! - 输出调度统计与业务执行结果汇总
//!
//! 依赖方向:presentation → interface → application → domain → common,
//! 符合严格分层(六层结构)。
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::dtos::process_dtos::{ProcessRequestDto, ProcessResponseDto};
use crate::domain::entities::jewelry::Jewelry;
use crate::domain::repository::process_repository::ProcessRecord;
use crate::infrastructure::di::container::ServiceContainer;
use crate::interface::contracts::BusinessEnvelope;
use crate::interface::ports::BusinessApiPort;
/// 应用控制器(控制台表现层,实现对外端口契约)
pub struct ApplicationController {
/// 依赖注入容器(组合根)
container: Arc<ServiceContainer>,
/// 统一日志对象
logger: Arc<dyn Logger>,
}
impl ApplicationController {
/// 创建应用控制器
///
/// # 参数
/// - `container`:依赖注入容器
///
/// # 返回
/// 应用控制器实例
pub fn new(container: Arc<ServiceContainer>) -> Self {
let logger = container.logger();
Self { container, logger }
}
/// 启动珠宝行业全程业务流程(中介者模式)演示
///
/// 流程:
/// ① 打印标题与配置
/// ② 创建珠宝实体
/// ③ 中介者顺序协调全部 12 个部门(含事件路由)
/// ④ 输出执行统计与记录明细
/// ⑤ 中介者并发调度全部部门(高并发演示)
/// ⑥ 通过端口契约派发单部门业务
pub fn run(&self) {
// ① 标题与运行说明
self.logger.info("================================================================");
self.logger.info(" 中介者模式 Mediator Pattern");
self.logger.info(" 珠宝行业企业级全程业务流程(DDD 六层分层)");
self.logger.info(" 业务:原料采购核验 · 设计制图 · 加工生产 · 质检 · 包装 · 物流");
self.logger.info(" · 财务 · 营销推广 · 业务销售 · 人事行政 · IT · 培训");
self.logger.info(" 日志:Logs/<日期>/app-{info,error,debug,warn}.log(按日期/等级分文件)");
self.logger.info("================================================================");
// ② 创建贯穿全流程的珠宝实体
let jewelry = Jewelry::new("六福传承金镯", "黄金", 35.68, 26800.0);
self.logger.info(&format!(
"创建珠宝实体:{},材质={},重量={} 克,零售价={} 元",
jewelry.name, jewelry.material, jewelry.weight_grams, jewelry.price
));
// ③ 中介者顺序协调全部 12 个部门(含事件路由,体现部门经中介者协同)
let request = ProcessRequestDto::new("ALL", jewelry.clone(), "调度中心", "Mediator");
self.container.service().coordinate(request);
self.logger.info("================================================================");
// ④ 输出执行统计(读取内存仓储)
self.print_summary();
// ⑤ 中介者并发调度全部部门(高并发演示)
self.logger.info("【高并发演示】中介者并发调度全部部门......");
let concurrent_request = ProcessRequestDto::new("ALL", jewelry.clone(), "调度中心", "Concurrent");
self.container.service().coordinate_concurrent(concurrent_request);
self.print_summary();
// ⑥ 通过端口契约派发单部门业务(BusinessEnvelope + dispatch)
let envelope = BusinessEnvelope::new(
"TRAINING",
ProcessRequestDto::new("TRAINING", jewelry, "培训部", "PortTest"),
);
match self.dispatch(&envelope.colleague_id, envelope.request) {
Ok(resp) => self.logger.info(&format!(
"端口契约派发单部门业务成功:{} / {}",
resp.process_name, resp.message
)),
Err(err) => self.logger.warn(&format!("端口契约派发单部门业务失败:{}", err)),
}
// ⑦ 输出已注册同事(部门)清单
let colleagues = self.container.service().colleagues();
self.logger
.info(&format!("已注册同事(部门)数:{}", colleagues.len()));
for colleague in colleagues {
self.logger.info(&format!(
" - [{}] {} / {}",
colleague.colleague_id(),
colleague.department(),
colleague.colleague_name()
));
}
self.logger.info("================================================================");
}
/// 输出执行统计与记录明细(基于仓储数据)
fn print_summary(&self) {
let (success, failure) = self.statistics();
self.logger.info(&format!(
"业务调度汇总:成功 {} 项,失败 {} 项(详见当日日志目录)",
success, failure
));
let records = self.records();
self.logger.info(&format!("执行记录明细(共 {} 条):", records.len()));
for record in records {
let flag = if record.outcome.success { "成功" } else { "失败" };
self.logger.info(&format!(
" - {} | {} | 状态:{} | 时间:{}",
record.instance_id, record.process_name, flag, record.executed_at
));
}
}
}
/// 实现对外 API 端口契约(interface 层定义)
impl BusinessApiPort for ApplicationController {
/// 派发并执行单部门业务(经中介者)
fn dispatch(
&self,
colleague_id: &str,
request: ProcessRequestDto,
) -> Result<ProcessResponseDto, ProcessError> {
self.container.service().execute_one(colleague_id, request)
}
/// 获取业务执行统计(成功数量,失败数量)
fn statistics(&self) -> (usize, usize) {
self.container.service().statistics()
}
/// 获取全部业务执行记录(用于追溯/汇总展示)
fn records(&self) -> Vec<ProcessRecord> {
self.container.service().records()
}
}

rust
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : business_sales.rs
//! 业务销售同事(中介者模式 Colleague 子类)
//!
//! 封装业务部业务:促成订单成交、定金与尾款收取。
//! 覆盖 `on_event`:收到「物流完成」「财务完成」「营销完成」事件时确认交付条件,
//! 体现销售环节经中介者对多部门的协同依赖。
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::{Colleague, ColleagueSupport};
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::{BusinessEvent, BusinessMediator};
/// 业务销售同事
pub struct BusinessSalesColleague {
/// 同事共享支持(日志 + 中介者引用)
support: ColleagueSupport,
}
impl BusinessSalesColleague {
/// 创建业务销售同事
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
support: ColleagueSupport::new(logger),
}
}
}
impl Colleague for BusinessSalesColleague {
/// 同事标识
fn colleague_id(&self) -> &'static str {
"SALES"
}
/// 同事名称
fn colleague_name(&self) -> &'static str {
"业务销售"
}
/// 所属部门
fn department(&self) -> &'static str {
"业务部"
}
/// 获取统一日志对象
fn logger(&self) -> &Arc<dyn Logger> {
self.support.logger()
}
/// 注入中介者
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
self.support.set_mediator(mediator);
}
/// 获取注入的中介者
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.support.mediator()
}
/// 执行业务:促成订单并收定金
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError> {
let jewelry = ctx.jewelry();
self.logger().info(&format!(
"【业务销售】客户下单购买 {},售价 {} 元,收取 30% 定金",
jewelry.name, jewelry.price
));
self.logger()
.info(&format!("【业务销售】生成销售订单并锁定库存"));
Ok(ProcessOutcome::success(
&ctx.instance_id,
"订单成交,定金已收取,待尾款结清后交付",
))
}
/// 响应中介者转发的事件:确认交付条件就绪
fn on_event(&self, event: BusinessEvent, _ctx: &CommandContext) -> Result<(), ProcessError> {
match event {
BusinessEvent::LogisticsCompleted => {
self.logger()
.info(&format!("【业务销售】经中介者确认物流已发货,可安排尾款结清交付"));
}
BusinessEvent::FinanceCompleted => {
self.logger()
.info(&format!("【业务销售】经中介者确认财务定价完成,可推进成交"));
}
BusinessEvent::MarketingCompleted => {
self.logger()
.info(&format!("【业务销售】经中介者确认营销投放完成,可承接客户咨询"));
}
_ => {}
}
Ok(())
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : design.rs
//! 设计制图同事(中介者模式 Colleague 子类)
//!
//! 封装设计部业务:根据原料进行款式设计与 CAD 制图。
//! 覆盖 `on_event`:收到「采购完成」事件时确认原料已就绪,体现经中介者协同。
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::{Colleague, ColleagueSupport};
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::{BusinessEvent, BusinessMediator};
/// 设计制图同事
pub struct DesignColleague {
/// 同事共享支持(日志 + 中介者引用)
support: ColleagueSupport,
}
impl DesignColleague {
/// 创建设计制图同事
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
support: ColleagueSupport::new(logger),
}
}
}
impl Colleague for DesignColleague {
/// 同事标识
fn colleague_id(&self) -> &'static str {
"DESIGN"
}
/// 同事名称
fn colleague_name(&self) -> &'static str {
"设计制图"
}
/// 所属部门
fn department(&self) -> &'static str {
"设计部"
}
/// 获取统一日志对象
fn logger(&self) -> &Arc<dyn Logger> {
self.support.logger()
}
/// 注入中介者
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
self.support.set_mediator(mediator);
}
/// 获取注入的中介者
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.support.mediator()
}
/// 执行业务:款式设计与 CAD 制图
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError> {
let jewelry = ctx.jewelry();
self.logger().info(&format!(
"【设计制图】为 {} 设计 3D 款式并输出 CAD 图纸",
jewelry.name
));
self.logger()
.info(&format!("【设计制图】完成建模、排石方案与工艺说明"));
Ok(ProcessOutcome::success(
&ctx.instance_id,
"设计图完成并通过初稿,图纸编号已归档",
))
}
/// 响应中介者转发的事件:采购完成 → 确认原料就绪
fn on_event(&self, event: BusinessEvent, _ctx: &CommandContext) -> Result<(), ProcessError> {
if event == BusinessEvent::ProcurementCompleted {
// 经中介者查询采购部门产出(体现同事经中介者间接通信)
let procurement = self
.mediator()
.and_then(|m| m.query("PROCUREMENT"));
self.logger().info(&format!(
"【设计制图】经中介者确认采购完成,原料产出:{}",
procurement
.map(|o| o.summary)
.unwrap_or_else(|| "(暂无产出记录)".to_string())
));
}
Ok(())
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : finance.rs
//! 财务同事(中介者模式 Colleague 子类)
//!
//! 封装财务部业务:成本归集、税费核算与凭证入账。
//! 覆盖 `on_event`:收到「采购完成」/「物流完成」事件时确认成本与回款依据。
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::{Colleague, ColleagueSupport};
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::{BusinessEvent, BusinessMediator};
/// 财务同事
pub struct FinanceColleague {
/// 同事共享支持(日志 + 中介者引用)
support: ColleagueSupport,
}
impl FinanceColleague {
/// 创建财务同事
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
support: ColleagueSupport::new(logger),
}
}
}
impl Colleague for FinanceColleague {
/// 同事标识
fn colleague_id(&self) -> &'static str {
"FINANCE"
}
/// 同事名称
fn colleague_name(&self) -> &'static str {
"财务"
}
/// 所属部门
fn department(&self) -> &'static str {
"财务部"
}
/// 获取统一日志对象
fn logger(&self) -> &Arc<dyn Logger> {
self.support.logger()
}
/// 注入中介者
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
self.support.set_mediator(mediator);
}
/// 获取注入的中介者
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.support.mediator()
}
/// 执行业务:成本归集与凭证入账
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError> {
let jewelry = ctx.jewelry();
let cost = jewelry.weight_grams * 480.0; // 模拟按克重折算采购成本
self.logger().info(&format!(
"【财务】核算 {} 采购成本:{:.2} 元,加工费 1200 元,税费 13%",
jewelry.name, cost
));
self.logger()
.info(&format!("【财务】生成成本核算单并完成记账凭证入账"));
Ok(ProcessOutcome::success(
&ctx.instance_id,
"财务核算完成,成本与税负已入账,凭证归档",
))
}
/// 响应中介者转发的事件:采购完成 → 确认成本依据
fn on_event(&self, event: BusinessEvent, _ctx: &CommandContext) -> Result<(), ProcessError> {
if event == BusinessEvent::ProcurementCompleted {
let procurement = self.mediator().and_then(|m| m.query("PROCUREMENT"));
self.logger().info(&format!(
"【财务】经中介者确认采购完成,成本依据:{}",
procurement
.map(|o| o.summary)
.unwrap_or_else(|| "(暂无产出记录)".to_string())
));
}
Ok(())
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : hr_admin.rs
//! 人事行政同事(中介者模式 Colleague 子类)
//!
//! 封装人事行政部业务:人员排班、考勤与行政资源保障。
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::{Colleague, ColleagueSupport};
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::BusinessMediator;
/// 人事行政同事
pub struct HrAdminColleague {
/// 同事共享支持(日志 + 中介者引用)
support: ColleagueSupport,
}
impl HrAdminColleague {
/// 创建人事行政同事
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
support: ColleagueSupport::new(logger),
}
}
}
impl Colleague for HrAdminColleague {
/// 同事标识
fn colleague_id(&self) -> &'static str {
"HR_ADMIN"
}
/// 同事名称
fn colleague_name(&self) -> &'static str {
"人事行政"
}
/// 所属部门
fn department(&self) -> &'static str {
"人事行政部"
}
/// 获取统一日志对象
fn logger(&self) -> &Arc<dyn Logger> {
self.support.logger()
}
/// 注入中介者
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
self.support.set_mediator(mediator);
}
/// 获取注入的中介者
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.support.mediator()
}
/// 执行业务:排班与行政保障
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError> {
let jewelry = ctx.jewelry();
self.logger().info(&format!(
"【人事行政】为 {} 生产项目排班技师与质检人员,并保障工位与物料行政资源",
jewelry.name
));
self.logger()
.info(&format!("【人事行政】考勤与加班工时已登记,行政资源调配完成"));
Ok(ProcessOutcome::success(
&ctx.instance_id,
"人员排班与行政保障完成,项目人力齐备",
))
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : inspection.rs
//! 质检同事(中介者模式 Colleague 子类)
//!
//! 封装质检部业务:对成品进行重量、成色、工艺、镶嵌牢固度检验。
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::{Colleague, ColleagueSupport};
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::BusinessMediator;
/// 质检同事
pub struct InspectionColleague {
/// 同事共享支持(日志 + 中介者引用)
support: ColleagueSupport,
}
impl InspectionColleague {
/// 创建质检同事
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
support: ColleagueSupport::new(logger),
}
}
}
impl Colleague for InspectionColleague {
/// 同事标识
fn colleague_id(&self) -> &'static str {
"INSPECTION"
}
/// 同事名称
fn colleague_name(&self) -> &'static str {
"质检"
}
/// 所属部门
fn department(&self) -> &'static str {
"质检部"
}
/// 获取统一日志对象
fn logger(&self) -> &Arc<dyn Logger> {
self.support.logger()
}
/// 注入中介者
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
self.support.set_mediator(mediator);
}
/// 获取注入的中介者
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.support.mediator()
}
/// 执行业务:成品质量检验
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError> {
let jewelry = ctx.jewelry();
self.logger().info(&format!(
"【质检】对 {} 进行重量复称、成色检测、工艺与镶嵌牢固度检验",
jewelry.name
));
if jewelry.weight_grams <= 0.0 {
return Err(ProcessError::new(
"WEIGHT_INVALID",
"质检发现成品克重异常,判定不合格",
));
}
self.logger().info(&format!(
"【质检】克重 {} 克复核通过,出具质检合格证书",
jewelry.weight_grams
));
Ok(ProcessOutcome::success(
&ctx.instance_id,
"质检合格,出具鉴定证书,可进入包装",
))
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : it.rs
//! IT 同事(中介者模式 Colleague 子类)
//!
//! 封装 IT 部业务:珠宝 ERP/进销存系统数据同步与系统保障。
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::{Colleague, ColleagueSupport};
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::BusinessMediator;
/// IT 同事
pub struct ItColleague {
/// 同事共享支持(日志 + 中介者引用)
support: ColleagueSupport,
}
impl ItColleague {
/// 创建 IT 同事
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
support: ColleagueSupport::new(logger),
}
}
}
impl Colleague for ItColleague {
/// 同事标识
fn colleague_id(&self) -> &'static str {
"IT"
}
/// 同事名称
fn colleague_name(&self) -> &'static str {
"IT"
}
/// 所属部门
fn department(&self) -> &'static str {
"IT部"
}
/// 获取统一日志对象
fn logger(&self) -> &Arc<dyn Logger> {
self.support.logger()
}
/// 注入中介者
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
self.support.set_mediator(mediator);
}
/// 获取注入的中介者
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.support.mediator()
}
/// 执行业务:系统数据同步与运行保障
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError> {
let jewelry = ctx.jewelry();
self.logger().info(&format!(
"【IT】为 {} 在 ERP 系统同步订单、库存与物流状态,并监控系统可用性",
jewelry.name
));
self.logger()
.info(&format!("【IT】数据库事务提交成功,系统健康检查通过"));
Ok(ProcessOutcome::success(
&ctx.instance_id,
"系统数据同步完成,业务运行保障正常",
))
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : logistics.rs
//! 物流发货同事(中介者模式 Colleague 子类)
//!
//! 封装物流部业务:出库、配送单生成与快递发出。
//! 该同事 `perform` 首次调用会瞬时失败(模拟外部物流系统不可用),
//! 经中介者的「重试 + 熔断」适配器自动重试后成功,演示弹性保护实际效果。
use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::{Colleague, ColleagueSupport};
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::BusinessMediator;
/// 外部物流系统调用计数(模拟前两次瞬时失败,第三次成功)
static LOGISTICS_CALL_COUNT: AtomicU32 = AtomicU32::new(0);
/// 物流发货同事
pub struct LogisticsColleague {
/// 同事共享支持(日志 + 中介者引用)
support: ColleagueSupport,
}
impl LogisticsColleague {
/// 创建物流发货同事
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
support: ColleagueSupport::new(logger),
}
}
}
impl Colleague for LogisticsColleague {
/// 同事标识
fn colleague_id(&self) -> &'static str {
"LOGISTICS"
}
/// 同事名称
fn colleague_name(&self) -> &'static str {
"物流"
}
/// 所属部门
fn department(&self) -> &'static str {
"物流部"
}
/// 获取统一日志对象
fn logger(&self) -> &Arc<dyn Logger> {
self.support.logger()
}
/// 注入中介者
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
self.support.set_mediator(mediator);
}
/// 获取注入的中介者
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.support.mediator()
}
/// 执行业务:物流发货(模拟外部系统瞬时失败 → 触发重试)
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError> {
let jewelry = ctx.jewelry();
// 模拟外部物流系统:前两次调用瞬时不可用(触发重试),第三次成功
let call = LOGISTICS_CALL_COUNT.fetch_add(1, Ordering::SeqCst);
if call < 2 {
self.logger().warn(&format!(
"【物流】外部物流系统暂时不可用(第 {} 次尝试)",
call + 1
));
return Err(ProcessError::new(
"LOGISTICS_TEMP_UNAVAILABLE",
"物流接口超时,等待重试",
));
}
self.logger().info(&format!(
"【物流】为 {} 生成配送单并安排顺丰/京东发货,运单已创建",
jewelry.name
));
self.logger()
.info(&format!("【物流】出库完成,物流节点进入在途状态"));
Ok(ProcessOutcome::success(
&ctx.instance_id,
"已发货,运单号生成,商品进入在途运输",
))
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : marketing.rs
//! 营销推广同事(中介者模式 Colleague 子类)
//!
//! 封装营销部业务:制定并投放新品推广方案。
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::{Colleague, ColleagueSupport};
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::BusinessMediator;
/// 营销推广同事
pub struct MarketingColleague {
/// 同事共享支持(日志 + 中介者引用)
support: ColleagueSupport,
}
impl MarketingColleague {
/// 创建营销推广同事
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
support: ColleagueSupport::new(logger),
}
}
}
impl Colleague for MarketingColleague {
/// 同事标识
fn colleague_id(&self) -> &'static str {
"MARKETING"
}
/// 同事名称
fn colleague_name(&self) -> &'static str {
"营销推广"
}
/// 所属部门
fn department(&self) -> &'static str {
"营销部"
}
/// 获取统一日志对象
fn logger(&self) -> &Arc<dyn Logger> {
self.support.logger()
}
/// 注入中介者
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
self.support.set_mediator(mediator);
}
/// 获取注入的中介者
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.support.mediator()
}
/// 执行业务:制定并投放推广方案
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError> {
let jewelry = ctx.jewelry();
self.logger().info(&format!(
"【营销推广】为 {} 制定新品推广方案:小红书种草 + 抖音直播 + 门店陈列",
jewelry.name
));
self.logger()
.info(&format!("【营销推广】推广素材已投放,曝光与转化数据开始回收"));
Ok(ProcessOutcome::success(
&ctx.instance_id,
"营销推广方案已投放,进入数据观测期",
))
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : packaging.rs
//! 包装同事(中介者模式 Colleague 子类)
//!
//! 封装包装部业务:礼盒包装、贴标、防伪封装。
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::{Colleague, ColleagueSupport};
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::BusinessMediator;
/// 包装同事
pub struct PackagingColleague {
/// 同事共享支持(日志 + 中介者引用)
support: ColleagueSupport,
}
impl PackagingColleague {
/// 创建包装同事
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
support: ColleagueSupport::new(logger),
}
}
}
impl Colleague for PackagingColleague {
/// 同事标识
fn colleague_id(&self) -> &'static str {
"PACKAGING"
}
/// 同事名称
fn colleague_name(&self) -> &'static str {
"包装"
}
/// 所属部门
fn department(&self) -> &'static str {
"包装部"
}
/// 获取统一日志对象
fn logger(&self) -> &Arc<dyn Logger> {
self.support.logger()
}
/// 注入中介者
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
self.support.set_mediator(mediator);
}
/// 获取注入的中介者
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.support.mediator()
}
/// 执行业务:礼盒包装与防伪封装
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError> {
let jewelry = ctx.jewelry();
self.logger().info(&format!(
"【包装】对 {} 进行礼盒包装、吊牌与防伪标签封装",
jewelry.name
));
self.logger()
.info(&format!("【包装】生成唯一防伪码并录入系统"));
Ok(ProcessOutcome::success(
&ctx.instance_id,
"包装完成,防伪码已生成,可交付物流发货",
))
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : procurement.rs
//! 原料采购核验同事(中介者模式 Colleague 子类)
//!
//! 封装采购部业务:核验材质并采购原料入库。
//! 覆盖 `on_event`:无额外协同响应(保持默认)。
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::{Colleague, ColleagueSupport};
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::BusinessMediator;
/// 原料采购核验同事
pub struct ProcurementColleague {
/// 同事共享支持(日志 + 中介者引用)
support: ColleagueSupport,
}
impl ProcurementColleague {
/// 创建原料采购核验同事
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
support: ColleagueSupport::new(logger),
}
}
}
impl Colleague for ProcurementColleague {
/// 同事标识
fn colleague_id(&self) -> &'static str {
"PROCUREMENT"
}
/// 同事名称
fn colleague_name(&self) -> &'static str {
"原料采购核验"
}
/// 所属部门
fn department(&self) -> &'static str {
"采购部"
}
/// 获取统一日志对象
fn logger(&self) -> &Arc<dyn Logger> {
self.support.logger()
}
/// 注入中介者
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
self.support.set_mediator(mediator);
}
/// 获取注入的中介者
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.support.mediator()
}
/// 执行业务:原料采购与第三方核验
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError> {
let jewelry = ctx.jewelry();
let supported = matches!(
jewelry.material.as_str(),
"黄金" | "铂金" | "钻石" | "K金" | "银"
);
if !supported {
return Err(ProcessError::new(
"INVALID_MATERIAL",
&format!("原料材质 {} 不在采购目录中", jewelry.material),
));
}
self.logger().info(&format!(
"【原料采购核验】向供应商采购原料:{},材质 {},重量 {} 克",
jewelry.name, jewelry.material, jewelry.weight_grams
));
self.logger()
.info(&format!("【原料采购核验】第三方质检机构核验通过(成色/克重)"));
Ok(ProcessOutcome::success(
&ctx.instance_id,
"原料采购完成,成色与克重符合标准,已入库待设计",
))
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : production.rs
//! 加工生产同事(中介者模式 Colleague 子类)
//!
//! 封装生产部业务:依据设计图进行浇铸、镶嵌、打磨。
//! 覆盖 `on_event`:收到「设计完成」事件时确认图纸就绪,体现经中介者协同。
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::{Colleague, ColleagueSupport};
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::{BusinessEvent, BusinessMediator};
/// 加工生产同事
pub struct ProductionColleague {
/// 同事共享支持(日志 + 中介者引用)
support: ColleagueSupport,
}
impl ProductionColleague {
/// 创建加工生产同事
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
support: ColleagueSupport::new(logger),
}
}
}
impl Colleague for ProductionColleague {
/// 同事标识
fn colleague_id(&self) -> &'static str {
"PRODUCTION"
}
/// 同事名称
fn colleague_name(&self) -> &'static str {
"加工生产"
}
/// 所属部门
fn department(&self) -> &'static str {
"生产部"
}
/// 获取统一日志对象
fn logger(&self) -> &Arc<dyn Logger> {
self.support.logger()
}
/// 注入中介者
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
self.support.set_mediator(mediator);
}
/// 获取注入的中介者
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.support.mediator()
}
/// 执行业务:加工生产
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError> {
if ctx.jewelry().name.trim().is_empty() {
return Err(ProcessError::new(
"PRODUCT_NAME_EMPTY",
"珠宝品名为空,无法进入加工生产",
));
}
let jewelry = ctx.jewelry();
self.logger().info(&format!(
"【加工生产】对 {} 执行浇铸 → 镶嵌 → 打磨工序",
jewelry.name
));
self.logger()
.info(&format!("【加工生产】成品初步成形,待质检部门检验"));
Ok(ProcessOutcome::success(
&ctx.instance_id,
"加工完成,成品初检合格,等待质检",
))
}
/// 响应中介者转发的事件:设计完成 → 确认图纸就绪
fn on_event(&self, event: BusinessEvent, _ctx: &CommandContext) -> Result<(), ProcessError> {
if event == BusinessEvent::DesignCompleted {
let design = self.mediator().and_then(|m| m.query("DESIGN"));
self.logger().info(&format!(
"【加工生产】经中介者确认设计完成,图纸产出:{}",
design
.map(|o| o.summary)
.unwrap_or_else(|| "(暂无产出记录)".to_string())
));
}
Ok(())
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : training.rs
//! 培训同事(中介者模式 Colleague 子类)
//!
//! 封装培训部业务:珠宝知识、工艺与销售话术培训及考核。
use std::sync::Arc;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::{Colleague, ColleagueSupport};
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::BusinessMediator;
/// 培训同事
pub struct TrainingColleague {
/// 同事共享支持(日志 + 中介者引用)
support: ColleagueSupport,
}
impl TrainingColleague {
/// 创建培训同事
///
/// # 参数
/// - `logger`:统一日志对象
///
/// # 返回
/// 同事实例
pub fn new(logger: Arc<dyn Logger>) -> Self {
Self {
support: ColleagueSupport::new(logger),
}
}
}
impl Colleague for TrainingColleague {
/// 同事标识
fn colleague_id(&self) -> &'static str {
"TRAINING"
}
/// 同事名称
fn colleague_name(&self) -> &'static str {
"培训"
}
/// 所属部门
fn department(&self) -> &'static str {
"培训部"
}
/// 获取统一日志对象
fn logger(&self) -> &Arc<dyn Logger> {
self.support.logger()
}
/// 注入中介者
fn set_mediator(&self, mediator: Arc<dyn BusinessMediator>) {
self.support.set_mediator(mediator);
}
/// 获取注入的中介者
fn mediator(&self) -> Option<Arc<dyn BusinessMediator>> {
self.support.mediator()
}
/// 执行业务:组织培训与考核
fn perform(&self, ctx: &CommandContext) -> Result<ProcessOutcome, ProcessError> {
let jewelry = ctx.jewelry();
self.logger().info(&format!(
"【培训】针对 {} 开展材质工艺、质检标准与销售话术专项培训",
jewelry.name
));
self.logger()
.info(&format!("【培训】完成培训考核,学员成绩合格并归档"));
Ok(ProcessOutcome::success(
&ctx.instance_id,
"培训完成,人员能力达标,考核记录已归档",
))
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : concrete_mediator.rs
//! 具体中介者实现(ConcreteMediator)
//!
//! 实现 `BusinessMediator` 契约,集中管理:
//! - 同事注册表(`Mutex<Vec<Arc<dyn Colleague>>>`,线程安全)
//! - 部门产出登记表(`Mutex<HashMap<colleague_id, ProcessOutcome>>`)
//! - 业务事件路由(dispatch:把某部门完成的事件转发给相关部门)
//! - 协调执行入口 `coordinate`:按珠宝业务链依次协调各部门,经「重试 + 熔断」保护
//! - 并发调度入口 `coordinate_concurrent`:多线程高并发执行全部同事
//!
//! 中介者是部门间交互的唯一通道,体现「同事不直接引用、经中介者集中解耦」。
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::Mutex;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::common::resilience::retry_circuit_breaker::RetryCircuitBreaker;
use crate::domain::dtos::process_dtos::{ProcessRequestDto, ProcessResponseDto};
use crate::domain::entities::jewelry::{next_sequence, ProcessOutcome};
use crate::domain::mediator::colleague::Colleague;
use crate::domain::mediator::command_ctx::CommandContext;
use crate::domain::mediator::mediator::{BusinessEvent, BusinessMediator};
/// 业务事件 → 接收部门映射(中介者决定事件路由)
fn receivers_for(event: BusinessEvent) -> &'static [&'static str] {
match event {
// 采购完成 → 通知 设计 / 财务 / 人事
BusinessEvent::ProcurementCompleted => &["DESIGN", "FINANCE", "HR_ADMIN"],
// 设计完成 → 通知 生产 / 营销
BusinessEvent::DesignCompleted => &["PRODUCTION", "MARKETING"],
// 生产完成 → 通知 质检
BusinessEvent::ProductionCompleted => &["INSPECTION"],
// 质检完成 → 通知 包装 / 财务
BusinessEvent::InspectionCompleted => &["PACKAGING", "FINANCE"],
// 包装完成 → 通知 物流
BusinessEvent::PackagingCompleted => &["LOGISTICS"],
// 物流完成 → 通知 财务 / IT / 业务
BusinessEvent::LogisticsCompleted => &["FINANCE", "IT", "SALES"],
// 财务完成 → 通知 业务
BusinessEvent::FinanceCompleted => &["SALES"],
// 营销完成 → 通知 业务
BusinessEvent::MarketingCompleted => &["SALES"],
// 业务完成 → 通知 人事
BusinessEvent::SalesCompleted => &["HR_ADMIN"],
// 人事完成 → 通知 培训
BusinessEvent::HrAdminCompleted => &["TRAINING"],
// IT / 培训 完成 → 无后续依赖
BusinessEvent::ItCompleted | BusinessEvent::TrainingCompleted => &[],
}
}
/// 具体中介者(线程安全)
pub struct ConcreteMediator {
/// 统一日志对象(依赖注入)
logger: Arc<dyn Logger>,
/// 重试 + 熔断适配器(依赖注入)
resilience: Arc<RetryCircuitBreaker>,
/// 同事注册表(受互斥锁保护)
colleagues: Mutex<Vec<Arc<dyn Colleague>>>,
/// 部门产出登记表(受互斥锁保护)
outputs: Mutex<HashMap<String, ProcessOutcome>>,
}
impl ConcreteMediator {
/// 创建具体中介者
///
/// # 参数
/// - `logger`:统一日志对象
/// - `resilience`:重试 + 熔断适配器
///
/// # 返回
/// 中介者实例
pub fn new(logger: Arc<dyn Logger>, resilience: Arc<RetryCircuitBreaker>) -> Self {
Self {
logger,
resilience,
colleagues: Mutex::new(Vec::new()),
outputs: Mutex::new(HashMap::new()),
}
}
/// 按珠宝业务链协调全部部门(体现中介者集中管理流程顺序与事件路由)
///
/// # 参数
/// - `request`:执行请求 DTO
///
/// # 返回
/// 各部门执行响应集合
pub fn coordinate(&self, request: ProcessRequestDto) -> Vec<ProcessResponseDto> {
self.logger.info("========== 中介者开始顺序协调珠宝全流程 ==========");
// 珠宝业务链顺序
let order = [
"PROCUREMENT",
"DESIGN",
"PRODUCTION",
"INSPECTION",
"PACKAGING",
"LOGISTICS",
"FINANCE",
"MARKETING",
"SALES",
"HR_ADMIN",
"IT",
"TRAINING",
];
let mut responses = Vec::new();
for colleague_id in order {
if let Some(colleague) = self.colleague(colleague_id) {
let instance_id = format!("{}-{:06}", colleague_id, next_sequence());
let ctx = CommandContext::new(&instance_id, request.clone());
responses.push(self.execute_colleague(&colleague, &ctx));
}
}
self.logger.info("========== 中介者顺序协调完成 ==========");
responses
}
/// 并发调度全部同事(多线程高并发演示,每个同事独立线程)
///
/// 通过 `self: &Arc<Self>` 在闭包中克隆共享同一中介者实例,
/// 保证同事注册表与产出登记表在多线程下一致。
///
/// # 参数
/// - `request`:执行请求 DTO
///
/// # 返回
/// 各部门执行响应集合
pub fn coordinate_concurrent(
self: &Arc<Self>,
request: ProcessRequestDto,
) -> Vec<ProcessResponseDto> {
self.logger.info("========== 中介者开始并发调度全部同事 ==========");
let mut handles = Vec::new();
for colleague in self.colleagues() {
let mediator = self.clone();
let request = request.clone();
let handle = std::thread::spawn(move || {
let instance_id = format!("{}-{:06}", colleague.colleague_id(), next_sequence());
let ctx = CommandContext::new(&instance_id, request);
mediator.execute_colleague(&colleague, &ctx)
});
handles.push(handle);
}
let mut responses = Vec::new();
for handle in handles {
responses.push(handle.join().unwrap());
}
self.logger.info("========== 中介者并发调度完成 ==========");
responses
}
/// 经「重试 + 熔断」执行单个同事业务,并登记产出、广播完成事件
///
/// # 参数
/// - `colleague`:同事
/// - `ctx`:命令上下文
///
/// # 返回
/// 执行响应 DTO
pub fn execute_colleague(
&self,
colleague: &Arc<dyn Colleague>,
ctx: &CommandContext,
) -> ProcessResponseDto {
self.logger.info(&format!(
"中介者协调执行部门「{}」实例={}",
colleague.colleague_name(),
ctx.instance_id
));
match self.resilience.execute(|| colleague.perform(ctx)) {
Ok(outcome) => {
// 登记部门产出(供其他部门经中介者查询)
self.record(colleague.colleague_id(), outcome.clone());
// 广播完成事件 → 中介者路由给相关部门
let event = BusinessEvent::from_colleague(colleague.colleague_id());
if let Err(err) = self.dispatch(colleague.colleague_id(), event, ctx) {
self.logger.warn(&format!(
"事件分发失败:事件={} 原因={}",
event.tag(),
err
));
}
ProcessResponseDto::new(
&ctx.instance_id,
colleague.colleague_name(),
true,
&outcome.summary,
)
}
Err(err) => {
self.logger.error(&format!(
"部门「{}」执行失败:{}(熔断状态={:?})",
colleague.colleague_name(),
err,
self.resilience.state()
));
ProcessResponseDto::new(
&ctx.instance_id,
colleague.colleague_name(),
false,
&format!("部门执行失败:{}", err),
)
}
}
}
}
impl BusinessMediator for ConcreteMediator {
/// 注册同事
fn register(&self, colleague: Arc<dyn Colleague>) {
self.colleagues.lock().unwrap().push(colleague);
}
/// 按标识查找同事
fn colleague(&self, colleague_id: &str) -> Option<Arc<dyn Colleague>> {
self.colleagues
.lock()
.unwrap()
.iter()
.find(|c| c.colleague_id() == colleague_id)
.cloned()
}
/// 获取全部已注册同事
fn colleagues(&self) -> Vec<Arc<dyn Colleague>> {
self.colleagues.lock().unwrap().clone()
}
/// 记录某部门的业务产出
fn record(&self, colleague_id: &str, outcome: ProcessOutcome) {
self.outputs
.lock()
.unwrap()
.insert(colleague_id.to_string(), outcome);
}
/// 查询某部门的业务产出(同事经中介者间接获取其他部门产出)
fn query(&self, colleague_id: &str) -> Option<ProcessOutcome> {
self.outputs.lock().unwrap().get(colleague_id).cloned()
}
/// 分发业务事件给相关部门(中介者集中管理部门间交互)
fn dispatch(
&self,
sender_id: &str,
event: BusinessEvent,
ctx: &CommandContext,
) -> Result<(), ProcessError> {
let receivers = receivers_for(event);
for receiver_id in receivers {
if *receiver_id == sender_id {
continue;
}
if let Some(colleague) = self.colleague(receiver_id) {
self.logger.debug(&format!(
"中介者将事件【{}】从 {} 路由给 {}",
event.tag(),
sender_id,
colleague.colleague_name()
));
// 调用接收部门的 on_event(同事经中介者间接协同)
if let Err(err) = colleague.on_event(event, ctx) {
self.logger.warn(&format!(
"部门「{}」响应事件失败:{}",
colleague.colleague_name(),
err
));
}
}
}
Ok(())
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : process_service.rs
//! 业务流程应用服务
//!
//! 职责:
//! - 持有具体中介者(`Arc<ConcreteMediator>`)
//!
//! 与仓储(构造器注入)
//! - 委托中介者执行顺序协调 / 并发调度
//! - 调用仓储保存执行记录
//! - 提供统计、记录查询、同事清单能力
//!
//! 全部日志通过统一日志对象(`Arc<dyn Logger>`)输出,控制台与文件一致。
use std::sync::Arc;
use crate::application::mediator::concrete_mediator::ConcreteMediator;
use crate::common::error::ProcessError;
use crate::common::logging::Logger;
use crate::domain::dtos::process_dtos::{ProcessRequestDto, ProcessResponseDto};
use crate::domain::entities::jewelry::ProcessOutcome;
use crate::domain::mediator::colleague::Colleague;
use crate::domain::mediator::mediator::BusinessMediator;
use crate::domain::repository::process_repository::{ProcessRecord, ProcessRepository};
/// 业务流程应用服务
pub struct ProcessService {
/// 具体中介者(依赖注入)
mediator: Arc<ConcreteMediator>,
/// 流程仓储(依赖注入)
repository: Arc<dyn ProcessRepository>,
/// 统一日志(依赖注入)
logger: Arc<dyn Logger>,
}
impl ProcessService {
/// 创建业务流程应用服务
///
/// # 参数
/// - `mediator`:具体中介者
/// - `repository`:流程仓储
/// - `logger`:统一日志
///
/// # 返回
/// 应用服务实例
pub fn new(
mediator: Arc<ConcreteMediator>,
repository: Arc<dyn ProcessRepository>,
logger: Arc<dyn Logger>,
) -> Self {
Self {
mediator,
repository,
logger,
}
}
/// 中介者顺序协调全部部门,并保存执行记录
///
/// # 参数
/// - `request`:执行请求 DTO
///
/// # 返回
/// 各部门执行响应集合
pub fn coordinate(&self, request: ProcessRequestDto) -> Vec<ProcessResponseDto> {
let responses = self.mediator.coordinate(request);
self.save_responses(&responses);
responses
}
/// 中介者并发调度全部部门(高并发演示),并保存执行记录
///
/// # 参数
/// - `request`:执行请求 DTO
///
/// # 返回
/// 各部门执行响应集合
pub fn coordinate_concurrent(&self, request: ProcessRequestDto) -> Vec<ProcessResponseDto> {
let responses = self.mediator.coordinate_concurrent(request);
self.save_responses(&responses);
responses
}
/// 保存一批执行记录(内部辅助)
///
/// # 参数
/// - `responses`:执行响应集合
fn save_responses(&self, responses: &[ProcessResponseDto]) {
for resp in responses {
let outcome = if resp.success {
ProcessOutcome::success(&resp.instance_id, &resp.message)
} else {
ProcessOutcome::failure(&resp.instance_id, &resp.message)
};
let record = ProcessRecord {
instance_id: resp.instance_id.clone(),
process_name: resp.process_name.clone(),
outcome,
executed_at: chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string(),
};
if let Err(err) = self.repository.save(record) {
self.logger.error(&format!("保存业务执行记录失败:{}", err));
}
}
}
/// 获取已注册同事清单(经中介者)
///
/// # 返回
/// 全部同事实例
pub fn colleagues(&self) -> Vec<Arc<dyn Colleague>> {
self.mediator.colleagues()
}
/// 获取业务执行统计(成功数量,失败数量)
///
/// # 返回
/// `(成功数量, 失败数量)` 元组
pub fn statistics(&self) -> (usize, usize) {
self.repository.count()
}
/// 获取全部业务执行记录(用于追溯/汇总展示)
///
/// # 返回
/// 全部执行记录
pub fn records(&self) -> Vec<ProcessRecord> {
self.repository.find_all()
}
/// 执行单个同事(供端口契约使用;经中介者重试熔断保护)
///
/// # 参数
/// - `colleague_id`:同事标识
/// - `request`:执行请求 DTO
///
/// # 返回
/// - `Ok(ProcessResponseDto)`:执行响应(成败见 `success` 字段)
/// - `Err(ProcessError)`:未找到同事
pub fn execute_one(
&self,
colleague_id: &str,
request: ProcessRequestDto,
) -> Result<ProcessResponseDto, ProcessError> {
let colleague = self.mediator.colleague(colleague_id).ok_or_else(|| {
ProcessError::new("NOT_FOUND", &format!("未找到同事:{}", colleague_id))
})?;
let instance_id = format!(
"{}-{:06}",
colleague_id,
crate::domain::entities::jewelry::next_sequence()
);
let ctx = crate::domain::mediator::command_ctx::CommandContext::new(&instance_id, request);
let response = self.mediator.execute_colleague(&colleague, &ctx);
Ok(response)
}
}
rust
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : retry_circuit_breaker.rs
//! 重试 + 熔断适配器(Resilience Adapter)
//!
//! 作用:在中介者协调同事执行依赖外部系统(如质检系统、物流接口、财务网关)时,
//! 提供「自动重试 + 熔断保护」:
//! - **重试**:瞬时失败时按指数退避重试,直至达到最大重试次数。
//! - **熔断**:连续失败达到阈值后打开熔断器,快速失败(不再重试),
//! 经冷却时间后进入半开状态,试探恢复。
//!
//! 线程安全:内部状态使用 `Mutex` 保护,可被 `Arc` 共享到多个线程高并发使用。
use std::sync::Mutex;
use std::time::{Duration, Instant};
use crate::common::error::ProcessError;
/// 熔断器打开错误码
const ERROR_CIRCUIT_OPEN: &str = "CIRCUIT_OPEN";
/// 熔断器状态
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CircuitState {
/// 关闭(正常运行,允许调用)
Closed,
/// 打开(熔断,快速失败)
Open,
/// 半开(冷却结束,试探性放行一次)
HalfOpen,
}
/// 熔断器内部状态(受互斥锁保护)
struct CircuitInner {
/// 当前熔断状态
state: CircuitState,
/// 连续失败次数
consecutive_failures: u32,
/// 熔断打开时刻(用于计算冷却时间)
opened_at: Option<Instant>,
}
/// 重试 + 熔断适配器(线程安全、可共享)
pub struct RetryCircuitBreaker {
/// 最大重试次数(成功之前最多额外尝试的次数)
max_retries: u32,
/// 熔断失败阈值(连续失败达到该次数即打开熔断器)
failure_threshold: u32,
/// 熔断冷却时间(打开后等待该时长才允许半开试探)
cooldown: Duration,
/// 内部熔断状态
inner: Mutex<CircuitInner>,
}
impl RetryCircuitBreaker {
/// 创建重试 + 熔断适配器
///
/// # 参数
/// - `max_retries`:最大重试次数
/// - `failure_threshold`:熔断失败阈值
/// - `cooldown`:熔断冷却时长
///
/// # 返回
/// 适配器实例
pub fn new(max_retries: u32, failure_threshold: u32, cooldown: Duration) -> Self {
Self {
max_retries,
failure_threshold,
cooldown,
inner: Mutex::new(CircuitInner {
state: CircuitState::Closed,
consecutive_failures: 0,
opened_at: None,
}),
}
}
/// 获取当前熔断状态(用于日志输出)
///
/// # 返回
/// 当前 `CircuitState`
pub fn state(&self) -> CircuitState {
self.inner
.lock()
.map(|g| g.state)
.unwrap_or(CircuitState::Closed)
}
/// 执行受保护的操作:带「重试 + 熔断」
///
/// # 泛型参数
/// - `F`:操作闭包类型
/// - `O`:成功返回值类型
///
/// # 参数
/// - `operation`:返回 `Result<O, ProcessError>` 的操作闭包
///
/// # 返回
/// - `Ok(O)`:操作最终成功
/// - `Err(ProcessError)`:重试耗尽或熔断快速失败
pub fn execute<F, O>(&self, operation: F) -> Result<O, ProcessError>
where
F: Fn() -> Result<O, ProcessError>,
{
// 步骤一:熔断前置检查(快速失败)
{
let mut guard = self.inner.lock().unwrap();
if guard.state == CircuitState::Open {
if let Some(opened_at) = guard.opened_at {
// 冷却时间未过 → 直接快速失败
if opened_at.elapsed() < self.cooldown {
return Err(ProcessError::new(
ERROR_CIRCUIT_OPEN,
"熔断器已打开,请求快速失败,请稍后重试",
));
}
}
// 冷却时间已过 → 转为半开状态,允许一次试探
guard.state = CircuitState::HalfOpen;
}
}
// 步骤二:带重试地执行操作
let mut attempt = 0u32;
loop {
match operation() {
Ok(value) => {
// 成功:重置失败计数,恢复关闭状态
let mut guard = self.inner.lock().unwrap();
guard.consecutive_failures = 0;
guard.state = CircuitState::Closed;
guard.opened_at = None;
return Ok(value);
}
Err(err) => {
attempt += 1;
{
let mut guard = self.inner.lock().unwrap();
guard.consecutive_failures += 1;
// 连续失败达到阈值 → 打开熔断器
if guard.consecutive_failures >= self.failure_threshold {
guard.state = CircuitState::Open;
guard.opened_at = Some(Instant::now());
return Err(err);
}
}
// 未熔断但重试次数已耗尽 → 返回错误
if attempt > self.max_retries {
return Err(err);
}
// 指数退避等待后重试
std::thread::sleep(Duration::from_millis(100 * attempt as u64));
}
}
}
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : error.rs
//! 统一错误类型定义
//!
//! 全项目统一使用 `ProcessError` 作为业务错误载体,携带错误码与消息,
//! 便于上层(应用层/接口层/表现层)统一捕获与日志输出。
/// 业务流程错误(统一错误载体)
#[derive(Debug, Clone)]
pub struct ProcessError {
/// 错误码(如 EXECUTION_FAILED / CIRCUIT_OPEN 等)
pub code: String,
/// 错误消息(中文,可直接输出到日志与界面)
pub message: String,
}
impl ProcessError {
/// 创建业务流程错误
///
/// # 参数
/// - `code`:错误码
/// - `message`:错误消息
///
/// # 返回
/// 构造好的 `ProcessError` 实例
pub fn new(code: &str, message: &str) -> Self {
Self {
code: code.to_string(),
message: message.to_string(),
}
}
}
/// 格式化输出(支持 `{}` 直接打印)
impl std::fmt::Display for ProcessError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[{}] {}", self.code, self.message)
}
}
/// 实现标准 Error trait,可向上转换为 `Box<dyn Error>`
impl std::error::Error for ProcessError {}
/// 预留的标准错误码字典(供上层业务模块调用,作为统一错误码契约预留给扩展)
#[allow(dead_code)]
pub mod error_code {
/// 前置校验失败
pub const VALIDATE_FAILED: &str = "VALIDATE_FAILED";
/// 业务执行失败
pub const EXECUTION_FAILED: &str = "EXECUTION_FAILED";
/// 熔断器打开(快速失败)
pub const CIRCUIT_OPEN: &str = "CIRCUIT_OPEN";
/// 资源未找到
pub const NOT_FOUND: &str = "NOT_FOUND";
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : logging.rs
//! 统一日志抽象接口(对应 C# 中的 `ILogger<T>`)
//!
//! 所有组件(调度器、中介者、同事、入口)仅依赖该接口输出日志,
//! 具体实现(文件日志)由基础设施层通过 DI 注入。
//! 保证控制台输出与日志文件输出格式完全一致。
//!
//! 日志文件规约:
//! ```text
//! Logs/
//! 2026-07-06/
//! app-info.log
//! app-error.log
//! app-debug.log
//! app-warn.log
//! ```
/// 日志等级
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LogLevel {
/// 调试(用于输出详细执行过程)
Debug,
/// 信息(用于输出常规流程状态)
Info,
/// 警告(用于输出可恢复异常)
Warn,
/// 错误(用于输出失败/异常)
Error,
}
impl LogLevel {
/// 获取日志等级标签(用于日志前缀,控制台与文件一致)
///
/// # 返回
/// 等级标签字符串
pub fn tag(&self) -> &'static str {
match self {
LogLevel::Debug => "DEBUG",
LogLevel::Info => "INFO",
LogLevel::Warn => "WARN",
LogLevel::Error => "ERROR",
}
}
/// 获取日志等级对应的文件名(按等级分文件)
///
/// # 返回
/// 文件名(如 `app-info.log`)
pub fn file_name(&self) -> &'static str {
match self {
LogLevel::Debug => "app-debug.log",
LogLevel::Info => "app-info.log",
LogLevel::Warn => "app-warn.log",
LogLevel::Error => "app-error.log",
}
}
}
/// 统一日志接口(线程安全、可对象化注入使用)
///
/// 设计要点:
/// - `Send + Sync` 保证可在多线程/高并发环境下共享(`Arc<dyn Logger>`)
/// - 方法非泛型,保持对象安全(object-safe),可向上转型为 trait 对象注入
pub trait Logger: Send + Sync {
/// 输出调试日志
///
/// # 参数
/// - `message`:日志消息
fn debug(&self, message: &str);
/// 输出信息日志
///
/// # 参数
/// - `message`:日志消息
fn info(&self, message: &str);
/// 输出警告日志
///
/// # 参数
/// - `message`:日志消息
fn warn(&self, message: &str);
/// 输出错误日志
///
/// # 参数
/// - `message`:日志消息
fn error(&self, message: &str);
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : result.rs
//! 统一结果返回类型
//!
//! 用于表现层/接口层向调用方返回统一结构的操作结果,保证输出格式一致。
/// 通用操作结果(泛型,表现层返回载体)
///
/// 预留给需要结构化返回(成功/失败 + 业务数据)的调用方使用;
/// 当前控制台演示直接输出日志,未构造该结果,属预留 API。
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ApiResult<T> {
/// 是否成功
pub success: bool,
/// 结果消息
pub message: String,
/// 业务数据(可选)
pub data: Option<T>,
}
impl<T> ApiResult<T> {
/// 创建成功结果
///
/// # 参数
/// - `data`:业务数据
///
/// # 返回
/// 成功结果
#[allow(dead_code)]
pub fn ok(data: T) -> Self {
Self {
success: true,
message: "操作成功".to_string(),
data: Some(data),
}
}
/// 创建失败结果
///
/// # 参数
/// - `message`:失败消息
///
/// # 返回
/// 失败结果
#[allow(dead_code)]
pub fn err(message: &str) -> Self {
Self {
success: false,
message: message.to_string(),
data: None,
}
}
}
调用:
rust
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:中介者模式Mediator Pattern 行为模式 Behavioral Patterns
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/10/21 21:39
//!# User : geovindu
//!# Product : RustRover
//!# Project : MediatorPattern
//!# File : main.rs
//! 中介者模式(Mediator Pattern)--- 珠宝行业企业级全程业务流程
//!
//! 业务范围:原料采购核验、设计制图、加工生产、质检、包装、物流、财务、
//! 营销推广、业务销售、人事行政、IT、培训。
//!
//! 中介者模式核心思想:
//! - **Colleague(同事)**:12 个业务部门各自封装业务动作,同事之间**不直接
//! 相互引用**,而是通过中介者通信。
//! - **Mediator(中介者)**:集中管理同事注册与事件路由,负责部门间的交互
//! 协调(如 采购完成 → 通知设计/财务;质检完成 → 通知包装/财务 等)。
//! - 通过中介者,部门间耦合被集中解耦,新增/替换部门不影响其他部门。
//!
//! 工程化特性:
//! - 日志按日期分文件夹、按日志等级分文件(Logs/2026-07-06/app-*.log)
//! - 注入统一日志对象 `Arc<dyn Logger>`(对应 C# 的 `ILogger<T>`)
//! - DTO 业务传输对象、适配器「重试 + 熔断」
//! - 兼容依赖注入(DI)、线程安全、高并发写入
//! - 调度器 / 同事 / 入口全部使用统一标准日志,控制台与文件输出完全一致
//!
//! DDD 严格分层(依赖方向:presentation → interface → application → domain → common;
//! infrastructure 实现 domain/interface 定义的接口):
//! - domain 领域层(实体、DTO、中介者/同事抽象、仓储接口)
//! - common 通用层(错误、结果、日志接口、重试熔断)
//! - application 应用层(具体中介者、12 个同事、应用服务)
//! - infrastructure 基础设施层(文件日志、DI 容器、内存仓储)
//! - interface 接口层(对外端口契约、命令信封契约)
//! - presentation 表现层(控制台入口 / 组合根装配 / 端口实现)
// 声明顶层模块(对应六个文件夹)
mod application;
mod common;
mod domain;
mod infrastructure;
mod interface;
mod presentation;
use std::sync::Arc;
use infrastructure::di::container::ServiceContainer;
use presentation::console::controller::ApplicationController;
/// 程序入口(组合根:装配依赖注入容器 → 创建应用控制器 → 启动中介者协调演示)
fn main() {
// 1. 构建依赖注入容器(组合根,统一装配全部服务与同事)
let container = Arc::new(ServiceContainer::new());
// 2. 创建应用控制器(表现层,实现 interface 定义的对外端口契约)
let controller = ApplicationController::new(container);
// 3. 启动珠宝行业全程业务流程(中介者模式)演示
controller.run();
}
输出:
