前言
在珠宝业务系统中,从原料采购、设计加工到质检、物流、财务、营销乃至人事培训,一条完整业务链路往往横跨多个部门。传统做法是各部门在流程节点上轮询或硬编码调用,导致模块之间高度耦合、扩展困难。观察者模式(Observer Pattern)通过「主题发布、观察者订阅」的方式,让业务阶段变更事件能够按需精准通知到对应部门,既降低了耦合,又提升了系统的可维护性与并发能力。本文以 C# .NET 10 为例,结合领域事件、依赖注入与重试熔断机制,完整演示观察者模式在珠宝全流程业务中的落地实践。
一、观察者模式核心概念
观察者模式属于行为型设计模式,核心思想是定义对象间一对多的依赖关系:当一个对象(主题 Subject)的状态发生变化时,所有依赖它的对象(观察者 Observer)都会收到通知并自动更新。在珠宝业务场景中,业务流程聚合根作为主题,各业务部门观察者订阅自己关心的阶段,从而实现业务链路的解耦与并行处理。
1.1 模式角色划分
- 主题(Subject) :维护观察者列表,提供注册、注销与通知方法,对应代码中的
IJewelBusinessSubject与JewelBusinessSubject。 - 观察者(Observer) :定义接收通知的更新接口,对应
IJewelObserver及各业务部门观察者实现。 - 具体主题(ConcreteSubject) :维护业务状态,状态变化时触发通知,对应
JewelBusinessFlow聚合根。 - 具体观察者(ConcreteObserver):实现具体的业务响应逻辑,对应采购部、设计部、质检部等观察者。
1.2 领域事件与观察者模式的结合
领域事件(Domain Event)是观察者模式在领域驱动设计(DDD)中的典型应用。当业务流程阶段发生变更时,聚合根产生一个 JewelStageChangedEvent 领域事件,主题将其发布给订阅了对应阶段的观察者。这种方式让业务规则与通知逻辑解耦,各观察者只需关心自己订阅的阶段,无需了解其他部门的处理细节。
二、珠宝业务观察者模式实战
本节基于 C# .NET 10 与 Visual Studio 2026,从领域模型、主题实现、观察者注册到高并发调度,逐步搭建完整的珠宝业务观察者模式示例。
2.1 领域模型与业务流程聚合根
首先定义珠宝原料、成品等实体,以及业务流程聚合根。聚合根维护全流程阶段顺序与状态机,通过 AdvanceToNextStage 方法推进业务阶段,并在阶段变更时产生领域事件。
2.2 主题与观察者接口设计
主题接口 IJewelBusinessSubject 负责订阅管理与事件发布;观察者接口 IJewelObserver 声明关心的阶段集合与事件处理方法。主题实现采用 ConcurrentDictionary 按阶段隔离订阅集合,锁粒度最小,保证高并发安全。
2.3 观察者注册与依赖注入
通过 JewelObserverRegistrar 统一注册全部业务部门观察者,并在 DI 容器中按需解析。各观察者声明自己关心的阶段,主题发布时按阶段精准分发,避免无关部门收到无效通知。
2.4 高并发调度与重试熔断
调度器 JewelFlowScheduler 并行运行多条业务流程,模拟高并发写入场景。结合重试熔断机制(ResilienceAdapter),当业务执行失败时自动重试,达到阈值则打开熔断,保护下游系统稳定。
三、运行效果与日志输出
运行示例程序后,调度器并行执行 8 条珠宝业务流程,各阶段变更事件按订阅关系精准通知对应部门观察者。日志按日期、按等级分类写入程序目录 Logs 文件夹,便于追踪每条流程的完整业务链路与执行结果。
3.1 项目结构说明
示例项目采用分层架构,包含领域层(Domain)、应用层(Application)、基础设施层(Infrastructure)与表现层(BLL),各层职责清晰,便于扩展与维护。
3.2 关键代码解读
主题实现中,ConcurrentDictionary<JewelStage, ConcurrentDictionary<IJewelObserver, byte>> 按阶段隔离订阅集合,发布时使用 Parallel 并行通知观察者,观察者经 ILogger 写日志,保证线程安全与高效分发。
总结
本文以珠宝全流程业务为背景,完整演示了观察者模式在 C# .NET 10 中的落地实践。通过领域事件解耦业务阶段与部门响应,结合依赖注入、并行调度与重试熔断机制,构建了一个高并发、易扩展、可维护的业务链路系统。观察者模式不仅适用于珠宝行业,在电商订单流转、审批流、消息推送等场景同样具有广泛的参考价值。
参考资料
- GoF 设计模式:可复用面向对象软件的基础(Erich Gamma 等)
- 领域驱动设计:软件核心复杂性应对之道(Eric Evans)
- Microsoft 官方文档:.NET 依赖注入与通用主机
- Microsoft 官方文档:ConcurrentDictionary 与并行编程
- Karambolo.Extensions.Logging.File:文件日志组件文档
项目结构:

cs
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : JewelBusinessFlow.cs
*/
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Domain.Entities
{
/// <summary>
/// 珠宝业务流程聚合根,维护业务流转顺序与状态机
/// </summary>
public sealed class JewelBusinessFlow
{
/// <summary>
/// 全流程固定阶段顺序(保证业务链闭环)
/// </summary>
private static readonly IReadOnlyList<JewelStage> StageSequence = new[]
{
JewelStage.RawMaterialVerify,
JewelStage.DesignDrawing,
JewelStage.Processing,
JewelStage.QualityInspection,
JewelStage.Packaging,
JewelStage.Logistics,
JewelStage.Finance,
JewelStage.Marketing,
JewelStage.SalesBusiness,
JewelStage.HrAdmin,
JewelStage.ItOps,
JewelStage.Training
};
/// <summary>
/// 业务流程实例 ID
/// </summary>
public string FlowId { get; }
/// <summary>
/// 关联原料
/// </summary>
public JewelRawMaterial RawMaterial { get; }
/// <summary>
/// 关联成品
/// </summary>
public JewelProduct Product { get; }
/// <summary>
/// 当前所处阶段
/// </summary>
public JewelStage CurrentStage { get; private set; }
/// <summary>
/// 流程状态:Running 运行中 / Completed 已完成 / Error 异常
/// </summary>
public string FlowStatus { get; private set; }
/// <summary>
/// 全流程只读阶段顺序(对外暴露)
/// </summary>
public IReadOnlyList<JewelStage> AllStages => StageSequence;
/// <summary>
/// 构造业务流程聚合根,初始状态为第一阶段的运行中
/// </summary>
/// <param name="flowId">流程 ID</param>
/// <param name="rawMaterial">原料</param>
/// <param name="product">成品</param>
public JewelBusinessFlow(string flowId, JewelRawMaterial rawMaterial, JewelProduct product)
{
FlowId = flowId;
RawMaterial = rawMaterial;
Product = product;
CurrentStage = StageSequence[0];
FlowStatus = "Running";
}
/// <summary>
/// 推进到下一阶段,返回新阶段;已是最后阶段则置为已完成并返回 null
/// </summary>
/// <returns>推进后的阶段,流程结束时返回 null</returns>
public JewelStage? AdvanceToNextStage()
{
// 找到当前阶段在顺序表中的索引
int currentIndex = Array.IndexOf([.. StageSequence], CurrentStage);
int nextIndex = currentIndex + 1;
// 已是最后一个阶段,标记完成
if (nextIndex >= StageSequence.Count)
{
FlowStatus = "Completed";
return null;
}
// 更新为下一阶段
CurrentStage = StageSequence[nextIndex];
return CurrentStage;
}
}
}
/*
encoding: utf-8
版权所有 2026 ©涂聚文有限公司™ ®
许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
Author : geovindu,Geovin Du 涂聚文.
IDE : vs2026 c# .net 10
os : windows 10
database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
Datetime : 2026/07/04 22:16
User : geovindu
Product : Visual Studio 2026
Project : CSharpDesignPattern
File : JewelProduct.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Domain.Entities
{
/// <summary>
/// 珠宝成品实体(领域模型)
/// </summary>
public sealed class JewelProduct
{
/// <summary>
/// 成品唯一编号
/// </summary>
public string ProductCode { get; }
/// <summary>
/// 成品名称(如"钻石吊坠")
/// </summary>
public string ProductName { get; }
/// <summary>
/// 零售定价(元)
/// </summary>
public decimal RetailPrice { get; }
/// <summary>
/// 构造成品实体
/// </summary>
/// <param name="productCode">成品编号</param>
/// <param name="productName">成品名称</param>
/// <param name="retailPrice">零售定价</param>
public JewelProduct(string productCode, string productName, decimal retailPrice)
{
ProductCode = productCode;
ProductName = productName;
RetailPrice = retailPrice;
}
}
}
/*
encoding: utf-8
版权所有 2026 ©涂聚文有限公司™ ®
许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
Author : geovindu,Geovin Du 涂聚文.
IDE : vs2026 c# .net 10
os : windows 10
database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
Datetime : 2026/07/04 22:16
User : geovindu
Product : Visual Studio 2026
Project : CSharpDesignPattern
File : JewelRawMaterial.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Domain.Entities
{
/// <summary>
/// 珠宝原料实体(领域模型)
/// </summary>
public sealed class JewelRawMaterial
{
/// <summary>
/// 原料唯一编号
/// </summary>
public string RawMaterialId { get; }
/// <summary>
/// 原料类型:黄金/铂金/钻石/宝石
/// </summary>
public string MaterialType { get; }
/// <summary>
/// 原料重量
/// </summary>
public decimal Weight { get; }
/// <summary>
/// 供应商名称
/// </summary>
public string SupplierName { get; }
/// <summary>
/// 采购核验是否通过
/// </summary>
public bool IsVerifyPass { get; }
/// <summary>
/// 构造原料实体
/// </summary>
/// <param name="rawMaterialId">原料编号</param>
/// <param name="materialType">原料类型</param>
/// <param name="weight">原料重量</param>
/// <param name="supplierName">供应商名称</param>
/// <param name="isVerifyPass">核验结果</param>
public JewelRawMaterial(
string rawMaterialId,
string materialType,
decimal weight,
string supplierName,
bool isVerifyPass)
{
RawMaterialId = rawMaterialId;
MaterialType = materialType;
Weight = weight;
SupplierName = supplierName;
IsVerifyPass = isVerifyPass;
}
}
}
/*
encoding: utf-8
版权所有 2026 ©涂聚文有限公司™ ®
许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
Author : geovindu,Geovin Du 涂聚文.
IDE : vs2026 c# .net 10
os : windows 10
database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
Datetime : 2026/07/04 22:16
User : geovindu
Product : Visual Studio 2026
Project : CSharpDesignPattern
File : DomainEventBase.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Domain.Events
{
/// <summary>
/// 领域事件基类,所有领域事件继承该类
/// </summary>
public abstract class DomainEventBase
{
/// <summary>
/// 事件唯一标识
/// </summary>
public Guid EventId { get; }
/// <summary>
/// 事件发生时间戳(UTC)
/// </summary>
public DateTime OccurTimeUtc { get; }
/// <summary>
/// 构造领域事件基类,初始化唯一标识与时间戳
/// </summary>
protected DomainEventBase()
{
EventId = Guid.NewGuid();
OccurTimeUtc = DateTime.UtcNow;
}
}
}
/*
encoding: utf-8
版权所有 2026 ©涂聚文有限公司™ ®
许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
Author : geovindu,Geovin Du 涂聚文.
IDE : vs2026 c# .net 10
os : windows 10
database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
Datetime : 2026/07/04 22:16
User : geovindu
Product : Visual Studio 2026
Project : CSharpDesignPattern
File : JewelStageChangedEvent.cs
*/
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Domain.Events
{
/// <summary>
/// 珠宝业务流程阶段变更领域事件,由主题发布、观察者消费
/// </summary>
public sealed class JewelStageChangedEvent : DomainEventBase
{
/// <summary>
/// 业务流程实例 ID
/// </summary>
public string FlowId { get; }
/// <summary>
/// 当前所处业务阶段
/// </summary>
public JewelStage Stage { get; }
/// <summary>
/// 成品编号
/// </summary>
public string ProductCode { get; }
/// <summary>
/// 原料编号
/// </summary>
public string RawMaterialId { get; }
/// <summary>
/// 原料类型(黄金/铂金/钻石/宝石)
/// </summary>
public string MaterialType { get; }
/// <summary>
/// 原料重量(克/克拉)
/// </summary>
public decimal Weight { get; }
/// <summary>
/// 供应商名称
/// </summary>
public string SupplierName { get; }
/// <summary>
/// 构造阶段变更事件
/// </summary>
/// <param name="flowId">业务流程 ID</param>
/// <param name="stage">当前阶段</param>
/// <param name="productCode">成品编号</param>
/// <param name="rawMaterialId">原料编号</param>
/// <param name="materialType">原料类型</param>
/// <param name="weight">原料重量</param>
/// <param name="supplierName">供应商名称</param>
public JewelStageChangedEvent(
string flowId,
JewelStage stage,
string productCode,
string rawMaterialId,
string materialType,
decimal weight,
string supplierName)
{
FlowId = flowId;
Stage = stage;
ProductCode = productCode;
RawMaterialId = rawMaterialId;
MaterialType = materialType;
Weight = weight;
SupplierName = supplierName;
}
}
}
/*
encoding: utf-8
版权所有 2026 ©涂聚文有限公司™ ®
许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
Author : geovindu,Geovin Du 涂聚文.
IDE : vs2026 c# .net 10
os : windows 10
database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
Datetime : 2026/07/04 22:16
User : geovindu
Product : Visual Studio 2026
Project : CSharpDesignPattern
File : IJewelBusinessSubject.cs
*/
using ObserverPattern.Domain.Events;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Domain.Interfaces
{
/// <summary>
/// 业务主题(发布者)接口,负责订阅管理与事件发布
/// </summary>
public interface IJewelBusinessSubject
{
/// <summary>
/// 注册(订阅)观察者
/// </summary>
/// <param name="observer">观察者实例</param>
void Attach(IJewelObserver observer);
/// <summary>
/// 注销(退订)观察者
/// </summary>
/// <param name="observer">观察者实例</param>
void Detach(IJewelObserver observer);
/// <summary>
/// 发布业务阶段变更事件,通知对应阶段的全部观察者
/// </summary>
/// <param name="evt">阶段变更事件</param>
void Notify(JewelStageChangedEvent evt);
}
}
/*
encoding: utf-8
版权所有 2026 ©涂聚文有限公司™ ®
许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
Author : geovindu,Geovin Du 涂聚文.
IDE : vs2026 c# .net 10
os : windows 10
database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
Datetime : 2026/07/04 22:16
User : geovindu
Product : Visual Studio 2026
Project : CSharpDesignPattern
File : IJewelObserver.cs
*/
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Domain.Interfaces
{
/// <summary>
/// 观察者接口:所有业务部门观察者实现该接口,接收领域事件通知
/// </summary>
public interface IJewelObserver
{
/// <summary>
/// 本观察者关心的业务阶段集合(用于主题按阶段精准分发,降低耦合)
/// </summary>
IReadOnlyCollection<JewelStage> SubscribeStages { get; }
/// <summary>
/// 处理业务阶段变更事件
/// </summary>
/// <param name="evt">阶段变更领域事件</param>
void OnStageChanged(JewelStageChangedEvent evt);
}
}
/*
encoding: utf-8
版权所有 2026 ©涂聚文有限公司™ ®
许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
Author : geovindu,Geovin Du 涂聚文.
IDE : vs2026 c# .net 10
os : windows 10
database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
Datetime : 2026/07/04 22:16
User : geovindu
Product : Visual Studio 2026
Project : CSharpDesignPattern
File : JewelBusinessSubject.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Domain.Interfaces;
using ObserverPattern.Shared;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Domain.Services
{
/// <summary>
/// 业务主题实现(发布者 Subject)
/// 采用 ConcurrentDictionary 按阶段隔离订阅集合,锁粒度最小,高并发安全
/// 发布时用 Parallel 并行通知观察者,观察者经 ILogger 写日志(线程安全)
/// </summary>
public class JewelBusinessSubject : IJewelBusinessSubject
{
/// <summary>
/// 日志注入
/// </summary>
private readonly ILogger<JewelBusinessSubject> _logger;
/// <summary>
/// 阶段 -> 观察者集合的映射表(线程安全)
/// 内层值使用 ConcurrentDictionary<IJewelObserver, byte> 当集合用,key 即观察者,保证去重
/// </summary>
private readonly ConcurrentDictionary<JewelStage, ConcurrentDictionary<IJewelObserver, byte>> _observerMap;
/// <summary>
/// 构造主题,初始化映射表
/// </summary>
/// <param name="logger">日志实例</param>
public JewelBusinessSubject(ILogger<JewelBusinessSubject> logger)
{
_logger = logger;
_observerMap = new ConcurrentDictionary<JewelStage, ConcurrentDictionary<IJewelObserver, byte>>();
}
/// <summary>
/// 注册观察者:按观察者声明的关注阶段分别加入对应集合
/// </summary>
/// <param name="observer">观察者实例</param>
public void Attach(IJewelObserver observer)
{
// 遍历观察者关心的每个阶段
foreach (JewelStage stage in observer.SubscribeStages)
{
// 获取或新建该阶段的观察者集合
ConcurrentDictionary<IJewelObserver, byte> stageObservers =
_observerMap.GetOrAdd(stage, _ => new ConcurrentDictionary<IJewelObserver, byte>());
// 尝试加入,若已存在则忽略(原子操作,线程安全)
if (stageObservers.TryAdd(observer, 0))
{
_logger.LogDebug(
"观察者 {ObserverName} 订阅阶段 {Stage} 成功",
observer.GetType().Name, stage);
}
}
}
/// <summary>
/// 注销观察者:从其关注的各阶段集合中移除
/// </summary>
/// <param name="observer">观察者实例</param>
public void Detach(IJewelObserver observer)
{
// 遍历观察者关心的每个阶段
foreach (JewelStage stage in observer.SubscribeStages)
{
// 若该阶段集合存在则尝试移除
if (_observerMap.TryGetValue(stage, out ConcurrentDictionary<IJewelObserver, byte>? stageObservers)
&& stageObservers != null
&& stageObservers.TryRemove(observer, out _))
{
_logger.LogDebug(
"观察者 {ObserverName} 取消订阅阶段 {Stage}",
observer.GetType().Name, stage);
}
}
}
/// <summary>
/// 发布阶段变更事件:并行通知该阶段全部观察者,单个观察者异常不阻断其他观察者
/// </summary>
/// <param name="evt">阶段变更事件</param>
public void Notify(JewelStageChangedEvent evt)
{
// 取出该阶段的观察者集合
if (!_observerMap.TryGetValue(evt.Stage, out ConcurrentDictionary<IJewelObserver, byte>? stageObservers)
|| stageObservers == null || stageObservers.IsEmpty)
{
_logger.LogWarning("阶段 {Stage} 无任何观察者订阅,事件 FlowId:{FlowId} 被忽略",
evt.Stage, evt.FlowId);
return;
}
_logger.LogInformation(
"发布阶段事件 FlowId:{FlowId} 阶段:{Stage} 产品:{ProductCode},通知观察者数:{Count}",
evt.FlowId, evt.Stage, evt.ProductCode, stageObservers.Count);
// 并行通知,观察者日志经 ILogger 线程安全写入,高并发安全
Parallel.ForEach(stageObservers.Keys, observer =>
{
try
{
observer.OnStageChanged(evt);
}
catch (Exception ex)
{
// 单个观察者异常不阻断整体通知,记录错误日志
_logger.LogError(ex,
"通知观察者 {ObserverName} 处理阶段 {Stage} 事件时发生异常,FlowId:{FlowId}",
observer.GetType().Name, evt.Stage, evt.FlowId);
}
});
}
}
}
cs
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : IJewelFlowApplicationService.cs
*/
using ObserverPattern.Application.Dto;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Contracts
{
/// <summary>
/// 珠宝业务流程应用服务接口:定义完整业务用例
/// </summary>
public interface IJewelFlowApplicationService
{
/// <summary>
/// 创建业务流程并推进到下一阶段(发布领域事件)
/// </summary>
/// <param name="inputDto">流程创建输入 DTO</param>
/// <returns>流程当前 DTO</returns>
Task<JewelBusinessFlowDto> CreateAndAdvanceFlowAsync(JewelBusinessFlowDto inputDto);
/// <summary>
/// 运行完整珠宝业务链路(从采购核验到培训),每阶段发布领域事件
/// </summary>
/// <param name="inputDto">流程创建输入 DTO</param>
/// <returns>完成后的流程 DTO</returns>
Task<JewelBusinessFlowDto> RunFullFlowAsync(JewelBusinessFlowDto inputDto);
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : JewelBusinessFlowDto.cs
*/
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Dto
{
/// <summary>
/// 业务流程创建/查询传输对象
/// </summary>
public sealed class JewelBusinessFlowDto
{
/// <summary>
/// 业务流程实例 ID
/// </summary>
public string FlowId { get; set; } = string.Empty;
/// <summary>
/// 原料信息
/// </summary>
public JewelRawMaterialDto? RawMaterial { get; set; }
/// <summary>
/// 成品信息
/// </summary>
public JewelProductDto? Product { get; set; }
/// <summary>
/// 当前所处阶段
/// </summary>
public JewelStage CurrentStage { get; set; }
/// <summary>
/// 流程状态:Running/Completed/Error
/// </summary>
public string FlowStatus { get; set; } = "Running";
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : JewelProductDto.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Dto
{
/// <summary>
/// 珠宝成品数据传输对象
/// </summary>
public sealed class JewelProductDto
{
/// <summary>
/// 成品唯一编号
/// </summary>
public string ProductCode { get; set; } = string.Empty;
/// <summary>
/// 成品名称
/// </summary>
public string ProductName { get; set; } = string.Empty;
/// <summary>
/// 零售定价(元)
/// </summary>
public decimal RetailPrice { get; set; }
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : JewelRawMaterialDto.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Dto
{
/// <summary>
/// 珠宝原料数据传输对象(应用层边界对象)
/// </summary>
public sealed class JewelRawMaterialDto
{
/// <summary>
/// 原料唯一编号
/// </summary>
public string RawMaterialId { get; set; } = string.Empty;
/// <summary>
/// 原料类型:黄金/铂金/钻石/宝石
/// </summary>
public string MaterialType { get; set; } = string.Empty;
/// <summary>
/// 原料重量
/// </summary>
public decimal Weight { get; set; }
/// <summary>
/// 供应商名称
/// </summary>
public string SupplierName { get; set; } = string.Empty;
/// <summary>
/// 采购核验是否通过
/// </summary>
public bool IsVerifyPass { get; set; }
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : DesignDepartmentObserver.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers.Departments
{
/// <summary>
/// 设计制图部门观察者
/// </summary>
public class DesignDepartmentObserver : JewelDepartmentObserverBase
{
/// <summary>
/// 具体类型日志
/// </summary>
private readonly ILogger<DesignDepartmentObserver> _logger;
/// <summary>
/// 构造设计制图观察者
/// </summary>
/// <param name="logger">日志实例</param>
public DesignDepartmentObserver(ILogger<DesignDepartmentObserver> logger) : base(logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称
/// </summary>
public override string DepartmentName => "设计制图部门";
/// <summary>
/// 关注阶段:设计制图
/// </summary>
public override IReadOnlyCollection<JewelStage> SubscribeStages =>
new[] { JewelStage.DesignDrawing };
/// <summary>
/// 设计制图业务处理:3D 建模、结构出图、工艺参数输出
/// </summary>
/// <param name="evt">阶段事件</param>
protected override void HandleBusiness(JewelStageChangedEvent evt)
{
_logger.LogDebug("执行设计制图:成品 {ProductCode} 3D 建模与工艺图纸输出", evt.ProductCode);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : FinanceObserver.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers.Departments
{
/// <summary>
/// 财务部门观察者
/// </summary>
public class FinanceObserver : JewelDepartmentObserverBase
{
/// <summary>
/// 具体类型日志
/// </summary>
private readonly ILogger<FinanceObserver> _logger;
/// <summary>
/// 构造财务观察者
/// </summary>
/// <param name="logger">日志实例</param>
public FinanceObserver(ILogger<FinanceObserver> logger) : base(logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称
/// </summary>
public override string DepartmentName => "财务部门";
/// <summary>
/// 关注阶段:财务
/// </summary>
public override IReadOnlyCollection<JewelStage> SubscribeStages =>
new[] { JewelStage.Finance };
/// <summary>
/// 财务业务处理:成本核算、费用归集、应收应付记账
/// </summary>
/// <param name="evt">阶段事件</param>
protected override void HandleBusiness(JewelStageChangedEvent evt)
{
_logger.LogDebug("执行财务:成品 {ProductCode} 成本核算与应收应付记账", evt.ProductCode);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : HrAdminObserver.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers.Departments
{
/// <summary>
/// 人事行政部门观察者
/// </summary>
public class HrAdminObserver : JewelDepartmentObserverBase
{
/// <summary>
/// 具体类型日志
/// </summary>
private readonly ILogger<HrAdminObserver> _logger;
/// <summary>
/// 构造人事行政观察者
/// </summary>
/// <param name="logger">日志实例</param>
public HrAdminObserver(ILogger<HrAdminObserver> logger) : base(logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称
/// </summary>
public override string DepartmentName => "人事行政部门";
/// <summary>
/// 关注阶段:人事行政
/// </summary>
public override IReadOnlyCollection<JewelStage> SubscribeStages =>
new[] { JewelStage.HrAdmin };
/// <summary>
/// 人事行政业务处理:人力评估、产能人力调度、后勤保障
/// </summary>
/// <param name="evt">阶段事件</param>
protected override void HandleBusiness(JewelStageChangedEvent evt)
{
_logger.LogDebug("执行人事行政:业务人力评估与后勤保障", evt.FlowId);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : ItDepartmentObserver.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers.Departments
{
/// <summary>
/// IT 运维部门观察者
/// </summary>
public class ItDepartmentObserver : JewelDepartmentObserverBase
{
/// <summary>
/// 具体类型日志
/// </summary>
private readonly ILogger<ItDepartmentObserver> _logger;
/// <summary>
/// 构造 IT 运维观察者
/// </summary>
/// <param name="logger">日志实例</param>
public ItDepartmentObserver(ILogger<ItDepartmentObserver> logger) : base(logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称
/// </summary>
public override string DepartmentName => "IT运维部门";
/// <summary>
/// 关注阶段:IT 运维
/// </summary>
public override IReadOnlyCollection<JewelStage> SubscribeStages =>
new[] { JewelStage.ItOps };
/// <summary>
/// IT 运维业务处理:链路日志采集、系统监控、异常告警
/// </summary>
/// <param name="evt">阶段事件</param>
protected override void HandleBusiness(JewelStageChangedEvent evt)
{
_logger.LogDebug("执行 IT 运维:流程 {FlowId} 链路日志采集与系统监控", evt.FlowId);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : LogisticsObserver.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers.Departments
{
/// <summary>
/// 物流部门观察者
/// </summary>
public class LogisticsObserver : JewelDepartmentObserverBase
{
/// <summary>
/// 具体类型日志
/// </summary>
private readonly ILogger<LogisticsObserver> _logger;
/// <summary>
/// 构造物流观察者
/// </summary>
/// <param name="logger">日志实例</param>
public LogisticsObserver(ILogger<LogisticsObserver> logger) : base(logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称
/// </summary>
public override string DepartmentName => "物流部门";
/// <summary>
/// 关注阶段:物流
/// </summary>
public override IReadOnlyCollection<JewelStage> SubscribeStages =>
new[] { JewelStage.Logistics };
/// <summary>
/// 物流业务处理:高值保价出库、物流单号生成、在途跟踪
/// </summary>
/// <param name="evt">阶段事件</param>
protected override void HandleBusiness(JewelStageChangedEvent evt)
{
_logger.LogDebug("执行物流:成品 {ProductCode} 保价出库与在途跟踪", evt.ProductCode);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : ObserverBll.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers.Departments
{
/// <summary>
/// 营销推广部门观察者
/// </summary>
public class MarketingObserver : JewelDepartmentObserverBase
{
/// <summary>
/// 具体类型日志
/// </summary>
private readonly ILogger<MarketingObserver> _logger;
/// <summary>
/// 构造营销推广观察者
/// </summary>
/// <param name="logger">日志实例</param>
public MarketingObserver(ILogger<MarketingObserver> logger) : base(logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称
/// </summary>
public override string DepartmentName => "营销推广部门";
/// <summary>
/// 关注阶段:营销推广
/// </summary>
public override IReadOnlyCollection<JewelStage> SubscribeStages =>
new[] { JewelStage.Marketing };
/// <summary>
/// 营销推广业务处理:新品素材、线上线下推广配置
/// </summary>
/// <param name="evt">阶段事件</param>
protected override void HandleBusiness(JewelStageChangedEvent evt)
{
_logger.LogDebug("执行营销推广:成品 {ProductCode} 新品推广素材与活动配置", evt.ProductCode);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : PackObserver.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers.Departments
{
/// <summary>
/// 包装部门观察者
/// </summary>
public class PackObserver : JewelDepartmentObserverBase
{
/// <summary>
/// 具体类型日志
/// </summary>
private readonly ILogger<PackObserver> _logger;
/// <summary>
/// 构造包装观察者
/// </summary>
/// <param name="logger">日志实例</param>
public PackObserver(ILogger<PackObserver> logger) : base(logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称
/// </summary>
public override string DepartmentName => "包装部门";
/// <summary>
/// 关注阶段:包装
/// </summary>
public override IReadOnlyCollection<JewelStage> SubscribeStages =>
new[] { JewelStage.Packaging };
/// <summary>
/// 包装业务处理:礼盒、证书、防伪标签封装
/// </summary>
/// <param name="evt">阶段事件</param>
protected override void HandleBusiness(JewelStageChangedEvent evt)
{
_logger.LogDebug("执行包装:成品 {ProductCode} 礼盒与证书封装", evt.ProductCode);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : ProduceDepartmentObserver.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers.Departments
{
/// <summary>
/// 加工生产部门观察者
/// </summary>
public class ProduceDepartmentObserver : JewelDepartmentObserverBase
{
/// <summary>
/// 具体类型日志
/// </summary>
private readonly ILogger<ProduceDepartmentObserver> _logger;
/// <summary>
/// 构造加工生产观察者
/// </summary>
/// <param name="logger">日志实例</param>
public ProduceDepartmentObserver(ILogger<ProduceDepartmentObserver> logger) : base(logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称
/// </summary>
public override string DepartmentName => "加工生产部门";
/// <summary>
/// 关注阶段:加工生产
/// </summary>
public override IReadOnlyCollection<JewelStage> SubscribeStages =>
new[] { JewelStage.Processing };
/// <summary>
/// 加工生产业务处理:铸造、镶嵌、抛光、执模
/// </summary>
/// <param name="evt">阶段事件</param>
protected override void HandleBusiness(JewelStageChangedEvent evt)
{
_logger.LogDebug("执行加工生产:成品 {ProductCode} 铸造/镶嵌/抛光工序启动", evt.ProductCode);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : PurchaseDepartmentObserver.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers.Departments
{
/// <summary>
/// 原料采购核验部门观察者
/// </summary>
public class PurchaseDepartmentObserver : JewelDepartmentObserverBase
{
/// <summary>
/// 具体类型日志
/// </summary>
private readonly ILogger<PurchaseDepartmentObserver> _logger;
/// <summary>
/// 构造采购核验观察者
/// </summary>
/// <param name="logger">日志实例</param>
public PurchaseDepartmentObserver(ILogger<PurchaseDepartmentObserver> logger) : base(logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称
/// </summary>
public override string DepartmentName => "原料采购核验部门";
/// <summary>
/// 关注阶段:原料采购核验
/// </summary>
public override IReadOnlyCollection<JewelStage> SubscribeStages =>
new[] { JewelStage.RawMaterialVerify };
/// <summary>
/// 采购核验业务处理:核对供应商资质、验金验石、登记入库
/// </summary>
/// <param name="evt">阶段事件</param>
protected override void HandleBusiness(JewelStageChangedEvent evt)
{
_logger.LogDebug(
"执行原料采购核验:原料 {RawId},类型 {MatType},重量 {Weight},供应商 {Supplier}",
evt.RawMaterialId, evt.MaterialType, evt.Weight, evt.SupplierName);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : QualityCheckObserver.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers.Departments
{
/// <summary>
/// 质检部门观察者
/// </summary>
public class QualityCheckObserver : JewelDepartmentObserverBase
{
/// <summary>
/// 具体类型日志
/// </summary>
private readonly ILogger<QualityCheckObserver> _logger;
/// <summary>
/// 构造质检观察者
/// </summary>
/// <param name="logger">日志实例</param>
public QualityCheckObserver(ILogger<QualityCheckObserver> logger) : base(logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称
/// </summary>
public override string DepartmentName => "质检部门";
/// <summary>
/// 关注阶段:质检
/// </summary>
public override IReadOnlyCollection<JewelStage> SubscribeStages =>
new[] { JewelStage.QualityInspection };
/// <summary>
/// 质检业务处理:贵金属纯度、宝石分级、外观瑕疵检验
/// </summary>
/// <param name="evt">阶段事件</param>
protected override void HandleBusiness(JewelStageChangedEvent evt)
{
_logger.LogDebug("执行质检:成品 {ProductCode} 纯度检测与外观瑕疵检验", evt.ProductCode);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : SalesBusinessObserver.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers.Departments
{
/// <summary>
/// 业务销售部门观察者
/// </summary>
public class SalesBusinessObserver : JewelDepartmentObserverBase
{
/// <summary>
/// 具体类型日志
/// </summary>
private readonly ILogger<SalesBusinessObserver> _logger;
/// <summary>
/// 构造业务销售观察者
/// </summary>
/// <param name="logger">日志实例</param>
public SalesBusinessObserver(ILogger<SalesBusinessObserver> logger) : base(logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称
/// </summary>
public override string DepartmentName => "业务销售部门";
/// <summary>
/// 关注阶段:业务销售
/// </summary>
public override IReadOnlyCollection<JewelStage> SubscribeStages =>
new[] { JewelStage.SalesBusiness };
/// <summary>
/// 业务销售处理:货品入库门店、库存同步、客户订单对接
/// </summary>
/// <param name="evt">阶段事件</param>
protected override void HandleBusiness(JewelStageChangedEvent evt)
{
_logger.LogDebug("执行业务销售:成品 {ProductCode} 入库门店与库存同步", evt.ProductCode);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : TrainingObserver.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers.Departments
{
/// <summary>
/// 员工培训部门观察者
/// </summary>
public class TrainingObserver : JewelDepartmentObserverBase
{
/// <summary>
/// 具体类型日志
/// </summary>
private readonly ILogger<TrainingObserver> _logger;
/// <summary>
/// 构造员工培训观察者
/// </summary>
/// <param name="logger">日志实例</param>
public TrainingObserver(ILogger<TrainingObserver> logger) : base(logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称
/// </summary>
public override string DepartmentName => "员工培训部门";
/// <summary>
/// 关注阶段:员工培训
/// </summary>
public override IReadOnlyCollection<JewelStage> SubscribeStages =>
new[] { JewelStage.Training };
/// <summary>
/// 员工培训业务处理:按新流程更新课件、安排实操培训
/// </summary>
/// <param name="evt">阶段事件</param>
protected override void HandleBusiness(JewelStageChangedEvent evt)
{
_logger.LogDebug("执行员工培训:根据流程 {FlowId} 更新岗位培训课件", evt.FlowId);
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : JewelDepartmentObserverBase.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Events;
using ObserverPattern.Domain.Interfaces;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers
{
/// <summary>
/// 部门观察者抽象基类:统一日志模板输出与生命周期,子类只需声明关注阶段与业务处理
/// 职责单一、完全可扩展------新增部门只需继承本类
/// </summary>
public abstract class JewelDepartmentObserverBase : IJewelObserver
{
/// <summary>
/// 日志抽象(子类注入的具体泛型日志)
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// 构造部门观察者基类
/// </summary>
/// <param name="logger">日志实例</param>
protected JewelDepartmentObserverBase(ILogger logger)
{
_logger = logger;
}
/// <summary>
/// 部门名称(用于日志标识)
/// </summary>
public abstract string DepartmentName { get; }
/// <summary>
/// 本部门关注的业务阶段集合
/// </summary>
public abstract IReadOnlyCollection<JewelStage> SubscribeStages { get; }
/// <summary>
/// 观察者入口:统一输出收到的阶段事件,再委托子类执行业务
/// </summary>
/// <param name="evt">阶段变更事件</param>
public void OnStageChanged(JewelStageChangedEvent evt)
{
// 统一日志模板,保证控制台与文件输出一致
_logger.LogInformation(
"[{Department}] 收到阶段事件 FlowId:{FlowId} 阶段:{Stage} 产品:{ProductCode}",
DepartmentName, evt.FlowId, evt.Stage, evt.ProductCode);
// 调用子类具体业务处理
HandleBusiness(evt);
}
/// <summary>
/// 子类实现的部门具体业务处理逻辑
/// </summary>
/// <param name="evt">阶段变更事件</param>
protected abstract void HandleBusiness(JewelStageChangedEvent evt);
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : JewelObserverRegistrar.cs
*/
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ObserverPattern.Domain.Interfaces;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Observers
{
/// <summary>
/// 观察者统一注册器:从 DI 容器取出全部部门观察者并订阅到主题
/// 职责单一------负责订阅装配;新增部门只需注册到 DI,本类自动装配
/// </summary>
public class JewelObserverRegistrar
{
/// <summary>
/// 业务主题
/// </summary>
private readonly IJewelBusinessSubject _subject;
/// <summary>
/// DI 服务提供器
/// </summary>
private readonly IServiceProvider _serviceProvider;
/// <summary>
/// 日志注入
/// </summary>
private readonly ILogger<JewelObserverRegistrar> _logger;
/// <summary>
/// 构造注册器
/// </summary>
/// <param name="subject">业务主题</param>
/// <param name="serviceProvider">DI 容器</param>
/// <param name="logger">日志实例</param>
public JewelObserverRegistrar(
IJewelBusinessSubject subject,
IServiceProvider serviceProvider,
ILogger<JewelObserverRegistrar> logger)
{
_subject = subject;
_serviceProvider = serviceProvider;
_logger = logger;
}
/// <summary>
/// 注册全部观察者:解析所有 IJewelObserver 实现并订阅到主题
/// </summary>
public void RegisterAllObservers()
{
// 从 DI 解析全部观察者实例
IEnumerable<IJewelObserver> observers = _serviceProvider.GetServices<IJewelObserver>();
// 逐个订阅
foreach (IJewelObserver observer in observers)
{
_subject.Attach(observer);
_logger.LogDebug("已注册观察者 {ObserverName}", observer.GetType().Name);
}
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : JewelFlowApplicationService.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Application.Contracts;
using ObserverPattern.Application.Dto;
using ObserverPattern.Domain.Entities;
using ObserverPattern.Domain.Events;
using ObserverPattern.Domain.Interfaces;
using ObserverPattern.Infrastructure.Resilience;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Application.Services
{
/// <summary>
/// 珠宝业务流程应用服务:负责用例编排、领域模型构建、事件发布
/// 使用重试熔断适配器包装对外/对内关键调用,职责单一、可扩展
/// </summary>
public class JewelFlowApplicationService : IJewelFlowApplicationService
{
/// <summary>
/// 业务主题(发布者)
/// </summary>
private readonly IJewelBusinessSubject _businessSubject;
/// <summary>
/// 重试熔断适配器
/// </summary>
private readonly IResilienceAdapter _resilienceAdapter;
/// <summary>
/// 日志注入
/// </summary>
private readonly ILogger<JewelFlowApplicationService> _logger;
/// <summary>
/// 构造应用服务,构造函数注入全部依赖(构造器注入)
/// </summary>
/// <param name="businessSubject">业务主题</param>
/// <param name="resilienceAdapter">重试熔断适配器</param>
/// <param name="logger">日志实例</param>
public JewelFlowApplicationService(
IJewelBusinessSubject businessSubject,
IResilienceAdapter resilienceAdapter,
ILogger<JewelFlowApplicationService> logger)
{
_businessSubject = businessSubject;
_resilienceAdapter = resilienceAdapter;
_logger = logger;
}
/// <summary>
/// 创建业务流程并推进到下一阶段,发布领域事件
/// </summary>
/// <param name="inputDto">流程创建输入</param>
/// <returns>流程当前状态 DTO</returns>
public Task<JewelBusinessFlowDto> CreateAndAdvanceFlowAsync(JewelBusinessFlowDto inputDto)
{
// 从 DTO 构建领域实体(应用层 -> 领域层)
JewelBusinessFlow flow = MapToEntity(inputDto);
// 获取当前阶段并构建事件
JewelStage currentStage = flow.CurrentStage;
JewelStageChangedEvent evt = BuildEvent(flow, currentStage);
// 通过重试熔断适配器发布事件,保证可靠投递
return _resilienceAdapter.ExecuteAsync(async () =>
{
_businessSubject.Notify(evt);
_logger.LogDebug("流程 {FlowId} 已发布阶段 {Stage} 事件", flow.FlowId, currentStage);
await Task.CompletedTask;
// 推进到下一阶段并返回当前状态
return MapToDto(flow);
});
}
/// <summary>
/// 运行完整业务链路,逐阶段推进并发布事件,带重试熔断保护
/// </summary>
/// <param name="inputDto">流程创建输入</param>
/// <returns>完成后的流程 DTO</returns>
public async Task<JewelBusinessFlowDto> RunFullFlowAsync(JewelBusinessFlowDto inputDto)
{
// 构建领域聚合根
JewelBusinessFlow flow = MapToEntity(inputDto);
_logger.LogInformation("流程 {FlowId} 开始运行完整业务链路", flow.FlowId);
// 每个阶段推进 + 发布事件(用重试熔断保护,防止偶发失败导致链路中断)
return await _resilienceAdapter.ExecuteAsync(async () =>
{
// 先发布当前阶段事件
_businessSubject.Notify(BuildEvent(flow, flow.CurrentStage));
// 循环推进到最后一阶段
JewelStage? nextStage;
while ((nextStage = flow.AdvanceToNextStage()) != null)
{
// 发布推进后阶段的领域事件
_businessSubject.Notify(BuildEvent(flow, nextStage.Value));
}
_logger.LogInformation("流程 {FlowId} 全部阶段执行完毕,状态:{Status}", flow.FlowId, flow.FlowStatus);
await Task.CompletedTask;
return MapToDto(flow);
});
}
/// <summary>
/// 根据聚合根与阶段构建领域事件
/// </summary>
/// <param name="flow">业务流程聚合根</param>
/// <param name="stage">当前阶段</param>
/// <returns>阶段变更事件</returns>
private static JewelStageChangedEvent BuildEvent(JewelBusinessFlow flow, JewelStage stage)
{
return new JewelStageChangedEvent(
flowId: flow.FlowId,
stage: stage,
productCode: flow.Product.ProductCode,
rawMaterialId: flow.RawMaterial.RawMaterialId,
materialType: flow.RawMaterial.MaterialType,
weight: flow.RawMaterial.Weight,
supplierName: flow.RawMaterial.SupplierName);
}
/// <summary>
/// 将输入 DTO 映射为领域聚合根
/// </summary>
/// <param name="inputDto">输入 DTO</param>
/// <returns>领域聚合根</returns>
private static JewelBusinessFlow MapToEntity(JewelBusinessFlowDto inputDto)
{
// 参数校验:原料与成品不可为空
ArgumentNullException.ThrowIfNull(inputDto.RawMaterial, nameof(inputDto.RawMaterial));
ArgumentNullException.ThrowIfNull(inputDto.Product, nameof(inputDto.Product));
// 映射原料实体
JewelRawMaterial material = new(
rawMaterialId: inputDto.RawMaterial.RawMaterialId,
materialType: inputDto.RawMaterial.MaterialType,
weight: inputDto.RawMaterial.Weight,
supplierName: inputDto.RawMaterial.SupplierName,
isVerifyPass: inputDto.RawMaterial.IsVerifyPass);
// 映射成品实体
JewelProduct product = new(
productCode: inputDto.Product.ProductCode,
productName: inputDto.Product.ProductName,
retailPrice: inputDto.Product.RetailPrice);
// 流程 ID 为空则生成新 ID
string flowId = string.IsNullOrWhiteSpace(inputDto.FlowId)
? Guid.NewGuid().ToString("N")
: inputDto.FlowId;
return new JewelBusinessFlow(flowId, material, product);
}
/// <summary>
/// 将领域聚合根映射为输出 DTO
/// </summary>
/// <param name="flow">领域聚合根</param>
/// <returns>输出 DTO</returns>
private static JewelBusinessFlowDto MapToDto(JewelBusinessFlow flow)
{
return new JewelBusinessFlowDto
{
FlowId = flow.FlowId,
CurrentStage = flow.CurrentStage,
FlowStatus = flow.FlowStatus,
RawMaterial = new JewelRawMaterialDto
{
RawMaterialId = flow.RawMaterial.RawMaterialId,
MaterialType = flow.RawMaterial.MaterialType,
Weight = flow.RawMaterial.Weight,
SupplierName = flow.RawMaterial.SupplierName,
IsVerifyPass = flow.RawMaterial.IsVerifyPass
},
Product = new JewelProductDto
{
ProductCode = flow.Product.ProductCode,
ProductName = flow.Product.ProductName,
RetailPrice = flow.Product.RetailPrice
}
};
}
}
}
cs
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : LoggingConfigurator.cs
*/
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Infrastructure.Logging
{
/// <summary>
/// 日志统一配置器:控制台与文件日志共用同一套 ILogger 抽象,保证输出内容一致
/// 文件日志由 Karambolo 实现按日期分文件夹、按等级分文件
/// </summary>
public static class LoggingConfigurator
{
/// <summary>
/// 扩展方法:配置日志提供程序
/// </summary>
/// <param name="builder">日志构建器</param>
/// <param name="configuration">应用配置</param>
/// <returns>日志构建器(链式)</returns>
public static ILoggingBuilder ConfigureEnterpriseLogging(
this ILoggingBuilder builder,
IConfiguration configuration)
{
// 清理默认提供程序,避免重复输出
builder.ClearProviders();
// 控制台日志
builder.AddConsole();
// Karambolo v4:配置绑定与提供程序注册分离
builder.AddConfiguration(configuration.GetSection("Logging"));
builder.AddFile();
// 最低日志等级
builder.SetMinimumLevel(LogLevel.Debug);
return builder;
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : IResilienceAdapter.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Infrastructure.Resilience
{
/// <summary>
/// 重试熔断适配器接口:统一为业务调用提供同步/异步容错
/// </summary>
public interface IResilienceAdapter
{
/// <summary>
/// 同步执行带重试熔断的业务委托
/// </summary>
/// <typeparam name="TResult">返回结果类型</typeparam>
/// <param name="func">业务委托</param>
/// <returns>业务结果</returns>
TResult Execute<TResult>(Func<TResult> func);
/// <summary>
/// 异步执行带重试熔断的业务委托
/// </summary>
/// <typeparam name="TResult">返回结果类型</typeparam>
/// <param name="func">异步业务委托</param>
/// <returns>业务结果 Task</returns>
Task<TResult> ExecuteAsync<TResult>(Func<Task<TResult>> func);
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : ResilienceAdapter.cs
*/
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Infrastructure.Resilience
{
/// <summary>
/// 重试熔断适配器实现
/// 用 lock 保护熔断状态计数与时间戳,保证多线程并发下安全
/// </summary>
public class ResilienceAdapter : IResilienceAdapter
{
/// <summary>
/// 配置项
/// </summary>
private readonly ResilienceOptions _options;
/// <summary>
/// 日志注入
/// </summary>
private readonly ILogger<ResilienceAdapter> _logger;
/// <summary>
/// 当前连续失败计数
/// </summary>
private int _currentFailCount;
/// <summary>
/// 熔断打开时间戳(UTC 毫秒),0 表示关闭
/// </summary>
private long _circuitBreakOpenTimestamp;
/// <summary>
/// 熔断状态访问锁
/// </summary>
private readonly object _stateLock = new();
/// <summary>
/// 构造适配器
/// </summary>
/// <param name="options">配置项</param>
/// <param name="logger">日志实例</param>
public ResilienceAdapter(ResilienceOptions options, ILogger<ResilienceAdapter> logger)
{
_options = options;
_logger = logger;
}
/// <summary>
/// 判断是否处于熔断打开状态;若超过熔断时长则自动半开恢复
/// </summary>
/// <returns>true=熔断打开拒绝执行,false=可执行</returns>
private bool IsCircuitBreakOpen()
{
lock (_stateLock)
{
// 未打开
if (_circuitBreakOpenTimestamp <= 0)
{
return false;
}
// 计算当前与打开时刻的间隔
long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
if (now - _circuitBreakOpenTimestamp > _options.CircuitBreakerBreakMs)
{
// 熔断窗口结束,进入半开状态并复位
_circuitBreakOpenTimestamp = 0;
_currentFailCount = 0;
_logger.LogInformation("熔断时间窗口结束,熔断器复位进入半开状态");
return false;
}
return true;
}
}
/// <summary>
/// 记录一次成功,复位失败计数器
/// </summary>
private void MarkSuccess()
{
lock (_stateLock)
{
_currentFailCount = 0;
}
}
/// <summary>
/// 记录一次失败,达阈值则打开熔断
/// </summary>
private void MarkFail()
{
lock (_stateLock)
{
_currentFailCount++;
// 连续失败达到阈值,打开熔断
if (_currentFailCount >= _options.CircuitBreakerErrorThreshold)
{
_circuitBreakOpenTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
_logger.LogWarning(
"连续失败达阈值 {Threshold},熔断器打开,熔断时长 {BreakMs}ms",
_options.CircuitBreakerErrorThreshold, _options.CircuitBreakerBreakMs);
}
}
}
/// <summary>
/// 同步执行:失败重试,达到熔断阈值抛异常
/// </summary>
/// <typeparam name="TResult">返回类型</typeparam>
/// <param name="func">业务委托</param>
/// <returns>业务结果</returns>
public TResult Execute<TResult>(Func<TResult> func)
{
// 熔断打开则直接拒绝
if (IsCircuitBreakOpen())
{
throw new InvalidOperationException("熔断器已打开,拒绝执行业务操作");
}
Exception? lastException = null;
// 重试循环
for (int attempt = 0; attempt <= _options.MaxRetryCount; attempt++)
{
try
{
TResult result = func.Invoke();
MarkSuccess();
return result;
}
catch (Exception ex)
{
lastException = ex;
MarkFail();
_logger.LogWarning(ex, "业务执行失败,第 {Attempt} 次重试", attempt);
// 非最后一次则等待后重试
if (attempt < _options.MaxRetryCount)
{
Thread.Sleep(_options.RetryDelayMs);
}
}
}
throw lastException!;
}
/// <summary>
/// 异步执行:失败重试,达到熔断阈值抛异常
/// </summary>
/// <typeparam name="TResult">返回类型</typeparam>
/// <param name="func">异步业务委托</param>
/// <returns>业务结果 Task</returns>
public async Task<TResult> ExecuteAsync<TResult>(Func<Task<TResult>> func)
{
// 熔断打开则直接拒绝
if (IsCircuitBreakOpen())
{
throw new InvalidOperationException("熔断器已打开,拒绝执行业务操作");
}
Exception? lastException = null;
// 重试循环
for (int attempt = 0; attempt <= _options.MaxRetryCount; attempt++)
{
try
{
TResult result = await func.Invoke();
MarkSuccess();
return result;
}
catch (Exception ex)
{
lastException = ex;
MarkFail();
_logger.LogWarning(ex, "异步业务执行失败,第 {Attempt} 次重试", attempt);
// 非最后一次则异步等待后重试
if (attempt < _options.MaxRetryCount)
{
await Task.Delay(_options.RetryDelayMs);
}
}
}
throw lastException!;
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : ResilienceOptions.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Infrastructure.Resilience
{
/// <summary>
/// 重试熔断策略配置项
/// </summary>
public sealed class ResilienceOptions
{
/// <summary>
/// 最大重试次数
/// </summary>
public int MaxRetryCount { get; set; } = 3;
/// <summary>
/// 重试间隔毫秒
/// </summary>
public int RetryDelayMs { get; set; } = 500;
/// <summary>
/// 熔断触发阈值:连续失败多少次打开熔断
/// </summary>
public int CircuitBreakerErrorThreshold { get; set; } = 5;
/// <summary>
/// 熔断恢复等待毫秒
/// </summary>
public int CircuitBreakerBreakMs { get; set; } = 3000;
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : JewelFlowScheduler.cs
*/
using Microsoft.Extensions.Logging;
using ObserverPattern.Application.Contracts;
using ObserverPattern.Application.Dto;
using ObserverPattern.Infrastructure.Resilience;
using ObserverPattern.Shared;
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Infrastructure.Scheduler
{
/// <summary>
/// 珠宝业务流程调度器:驱动完整业务链路,并模拟高并发(并行多个流程)
/// </summary>
public class JewelFlowScheduler
{
/// <summary>
/// 业务流程应用服务
/// </summary>
private readonly IJewelFlowApplicationService _flowService;
/// <summary>
/// 重试熔断适配器
/// </summary>
private readonly IResilienceAdapter _resilienceAdapter;
/// <summary>
/// 日志注入
/// </summary>
private readonly ILogger<JewelFlowScheduler> _logger;
/// <summary>
/// 构造调度器
/// </summary>
/// <param name="flowService">业务流程应用服务</param>
/// <param name="resilienceAdapter">重试熔断适配器</param>
/// <param name="logger">日志实例</param>
public JewelFlowScheduler(
IJewelFlowApplicationService flowService,
IResilienceAdapter resilienceAdapter,
ILogger<JewelFlowScheduler> logger)
{
_flowService = flowService;
_resilienceAdapter = resilienceAdapter;
_logger = logger;
}
/// <summary>
/// 运行高并发珠宝业务流程
/// </summary>
/// <param name="parallelCount">并行流程数量(模拟高并发)</param>
/// <returns>异步任务</returns>
public async Task RunAsync(int parallelCount)
{
_logger.LogInformation("===== 启动珠宝业务高并发调度,并行流程数:{ParallelCount} =====", parallelCount);
// 并行创建并运行多个流程,模拟高并发写入场景
Task[] tasks = Enumerable.Range(0, parallelCount)
.Select(index => RunOneFlowAsync(index))
.ToArray();
// 等待全部流程完成
await Task.WhenAll(tasks);
_logger.LogInformation("===== 珠宝业务高并发调度完成,共执行 {ParallelCount} 条流程 =====", parallelCount);
}
/// <summary>
/// 运行单条完整珠宝业务链路
/// </summary>
/// <param name="index">流程序号</param>
/// <returns>异步任务</returns>
private async Task RunOneFlowAsync(int index)
{
try
{
// 构建流程输入 DTO
JewelBusinessFlowDto inputDto = BuildFlowInput(index);
// 通过重试熔断适配器执行完整链路
await _resilienceAdapter.ExecuteAsync(() => _flowService.RunFullFlowAsync(inputDto));
_logger.LogInformation("流程 #{Index} 完整业务链路执行完成", index);
}
catch (Exception ex)
{
// 记录单条流程异常,不阻断其他流程
_logger.LogError(ex, "流程 #{Index} 执行失败", index);
}
}
/// <summary>
/// 构建流程输入 DTO(含原料与成品)
/// </summary>
/// <param name="index">流程序号</param>
/// <returns>流程输入 DTO</returns>
private static JewelBusinessFlowDto BuildFlowInput(int index)
{
// 生成基于序号+时间的唯一编号
string stamp = $"{DateTime.Now:yyyyMMddHHmmss}";
string rawId = $"RM{index}_{stamp}";
string productCode = $"JW{index}_{stamp}";
return new JewelBusinessFlowDto
{
FlowId = Guid.NewGuid().ToString("N"),
CurrentStage = JewelStage.RawMaterialVerify,
FlowStatus = "Running",
RawMaterial = new JewelRawMaterialDto
{
RawMaterialId = rawId,
MaterialType = "钻石",
Weight = 1.28m,
SupplierName = "环球宝石供应商",
IsVerifyPass = true
},
Product = new JewelProductDto
{
ProductCode = productCode,
ProductName = "璀璨钻石吊坠",
RetailPrice = 28888.00m
}
};
}
}
}
/*
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : JewelStage.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace ObserverPattern.Shared
{
/// <summary>
/// 珠宝全业务流程阶段枚举(共享常量,避免字符串魔法值)
/// </summary>
public enum JewelStage
{
/// <summary>
/// 原料采购核验
/// </summary>
RawMaterialVerify = 0,
/// <summary>
/// 设计制图
/// </summary>
DesignDrawing = 1,
/// <summary>
/// 加工生产
/// </summary>
Processing = 2,
/// <summary>
/// 质检
/// </summary>
QualityInspection = 3,
/// <summary>
/// 包装
/// </summary>
Packaging = 4,
/// <summary>
/// 物流
/// </summary>
Logistics = 5,
/// <summary>
/// 财务
/// </summary>
Finance = 6,
/// <summary>
/// 营销推广
/// </summary>
Marketing = 7,
/// <summary>
/// 业务销售
/// </summary>
SalesBusiness = 8,
/// <summary>
/// 人事行政
/// </summary>
HrAdmin = 9,
/// <summary>
/// IT 运维
/// </summary>
ItOps = 10,
/// <summary>
/// 员工培训
/// </summary>
Training = 11
}
}
调用:
cs
/*\
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:观察者模式 Observer Pattern 行为模式 Behavioral Patterns
# Author : geovindu,Geovin Du 涂聚文.
# IDE : vs2026 c# .net 10
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/07/04 22:16
# User : geovindu
# Product : Visual Studio 2026
# Project : CSharpDesignPattern
# File : ObserverBll.cs
*/
using System;
using System.Collections.Generic;
using System.Text;
using ObserverPattern.Application.Contracts;
using ObserverPattern.Application.Observers;
using ObserverPattern.Application.Observers.Departments;
using ObserverPattern.Application.Services;
using ObserverPattern.Domain.Interfaces;
using ObserverPattern.Domain.Services;
using ObserverPattern.Infrastructure.Logging;
using ObserverPattern.Infrastructure.Resilience;
using ObserverPattern.Infrastructure.Scheduler;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace BLL
{
/// <summary>
/// 可以扩展: 数据库持久化仓储、或把调度器改成 `Channel` 背压队列
/// </summary>
public class ObserverBll
{
public async Task Demo()
{
string[] args= { };
// 1. 构建通用主机并完成 DI 装配
using IHost host = BuildHost(args);
// 2. 从 DI 容器获取订阅器并注册全部观察者
using (IServiceScope scope = host.Services.CreateScope())
{
// 获取观察者注册器
JewelObserverRegistrar registrar =
scope.ServiceProvider.GetRequiredService<JewelObserverRegistrar>();
// 统一订阅全部业务部门观察者
registrar.RegisterAllObservers();
// 3. 获取高并发调度器并运行
JewelFlowScheduler scheduler =
scope.ServiceProvider.GetRequiredService<JewelFlowScheduler>();
// 并行运行 8 条流程,模拟高并发写入
await scheduler.RunAsync(parallelCount: 8);
}
Console.WriteLine("珠宝业务调度执行完毕,请在程序目录 Logs 下查看按日期、按等级分类的日志文件。");
Console.WriteLine("按回车键退出...");
Console.ReadLine();
}
/// <summary>
/// 构建通用主机:加载配置、注册 DI、配置日志(控制台+文件)
/// </summary>
/// <param name="args">命令行参数</param>
/// <returns>构建完成的通用主机</returns>
private static IHost BuildHost(string[] args)
{
return Host.CreateDefaultBuilder(args)
// 加载仓库根目录 appsettings.json(ContentRoot 默认在 BLL 目录,默认配置读不到根目录文件)
.ConfigureAppConfiguration((_, config) =>
{
string? configDir = Directory.GetCurrentDirectory();
while (configDir != null && !File.Exists(Path.Combine(configDir, "appsettings.json")))
{
configDir = Directory.GetParent(configDir)?.FullName;
}
if (configDir != null)
{
config.AddJsonFile(Path.Combine(configDir, "appsettings.json"), optional: false, reloadOnChange: true);
}
})
// 注册全部服务到 DI 容器
.ConfigureServices((context, services) =>
{
// ---- 领域层 ----
// 主题(发布者)注册为单例,全应用共享
services.AddSingleton<IJewelBusinessSubject, JewelBusinessSubject>();
// ---- 应用层 ----
// 业务流程应用服务
services.AddScoped<IJewelFlowApplicationService, JewelFlowApplicationService>();
// 观察者统一注册器
services.AddScoped<JewelObserverRegistrar>();
// 注册全部业务部门观察者(按需解析,装配时取出)
services.AddTransient<IJewelObserver, PurchaseDepartmentObserver>();
services.AddTransient<IJewelObserver, DesignDepartmentObserver>();
services.AddTransient<IJewelObserver, ProduceDepartmentObserver>();
services.AddTransient<IJewelObserver, QualityCheckObserver>();
services.AddTransient<IJewelObserver, PackObserver>();
services.AddTransient<IJewelObserver, LogisticsObserver>();
services.AddTransient<IJewelObserver, FinanceObserver>();
services.AddTransient<IJewelObserver, MarketingObserver>();
services.AddTransient<IJewelObserver, SalesBusinessObserver>();
services.AddTransient<IJewelObserver, HrAdminObserver>();
services.AddTransient<IJewelObserver, ItDepartmentObserver>();
services.AddTransient<IJewelObserver, TrainingObserver>();
// ---- 基础设施层 ----
// 重试熔断配置(从配置或默认值)
services.AddSingleton(_ => new ResilienceOptions
{
MaxRetryCount = 3,
RetryDelayMs = 600,
CircuitBreakerErrorThreshold = 4,
CircuitBreakerBreakMs = 5000
});
services.AddSingleton<IResilienceAdapter, ResilienceAdapter>();
// 高并发业务调度器
services.AddTransient<JewelFlowScheduler>();
})
// 配置日志:控制台 + Karambolo 文件日志,输出一致
.ConfigureLogging((context, logging) =>
{
logging.ConfigureEnterpriseLogging(context.Configuration);
})
.Build();
}
}
}
输出:
