moklgy's blog moklgy's blog
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 后端文章

    • 技术题
  • .netcore

    • 《asp.netcore》笔记
    • 《设计模式》
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

moklgy docs

全栈初级开发工程师
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 后端文章

    • 技术题
  • .netcore

    • 《asp.netcore》笔记
    • 《设计模式》
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 对象之间的关系
  • SOLID原则
  • 创建型
  • 结构型
  • 行为型一
    • 行为型模式一
      • 13. 责任链模式
      • 14. 命令模式
      • 15. 迭代器模式
      • 16. 中介者模式
      • 17. 备忘录模式
  • 行为型二
  • 其他模式与组合使用
  • 《设计模式》
moklgydocs
2025-10-12
目录

行为型一

# C#设计模式全面指南

# 行为型模式一

# 13. 责任链模式

原理:
责任链模式允许你将请求沿着处理者链进行发送。收到请求后,每个处理者可以处理请求或将其传递给链中的下一个处理者。

思路:

  1. 定义处理者接口,包含设置下一个处理者和处理请求的方法
  2. 创建具体处理者类,实现处理者接口
  3. 构建处理者链,每个处理者知道链中的下一个处理者
  4. 客户端将请求发送到链的第一个处理者

前辈经验:

  • 当系统需要按指定顺序处理请求或有多个处理者可能处理请求时,使用责任链模式
  • 责任链可以降低发送者和接收者之间的耦合,发送者不需要知道谁会处理请求
  • 处理者可以动态添加或移除,使系统更灵活
  • 注意避免请求在链中被遗忘,如果链中没有处理者处理请求,可能需要默认处理者
  • 长链可能导致性能问题,并使调试变得困难

业务场景:
审批系统,不同级别的经理根据请求金额有不同的审批权限。

简单实现:

// 请求类
public class PurchaseRequest
{
    public string RequestId { get; set; }
    public string Description { get; set; }
    public double Amount { get; set; }
    
    public PurchaseRequest(string requestId, string description, double amount)
    {
        RequestId = requestId;
        Description = description;
        Amount = amount;
    }
}

// 处理者接口
public abstract class Approver
{
    protected Approver _nextApprover;
    protected string _name;
    
    public Approver(string name)
    {
        _name = name;
    }
    
    public void SetNext(Approver nextApprover)
    {
        _nextApprover = nextApprover;
    }
    
    public abstract void ProcessRequest(PurchaseRequest request);
}

// 具体处理者 - 部门经理
public class DepartmentManager : Approver
{
    public DepartmentManager(string name) : base(name)
    {
    }
    
    public override void ProcessRequest(PurchaseRequest request)
    {
        if (request.Amount <= 10000.0)
        {
            Console.WriteLine($"{_name} 部门经理批准了采购请求 {request.RequestId}: {request.Description}, 金额: ${request.Amount}");
        }
        else if (_nextApprover != null)
        {
            Console.WriteLine($"{_name} 部门经理无权批准 ${request.Amount} 的请求,转交给上级");
            _nextApprover.ProcessRequest(request);
        }
        else
        {
            Console.WriteLine($"请求 {request.RequestId} 无法批准,没有足够权限的审批人");
        }
    }
}

// 具体处理者 - 总监
public class Director : Approver
{
    public Director(string name) : base(name)
    {
    }
    
    public override void ProcessRequest(PurchaseRequest request)
    {
        if (request.Amount <= 50000.0)
        {
            Console.WriteLine($"{_name} 总监批准了采购请求 {request.RequestId}: {request.Description}, 金额: ${request.Amount}");
        }
        else if (_nextApprover != null)
        {
            Console.WriteLine($"{_name} 总监无权批准 ${request.Amount} 的请求,转交给上级");
            _nextApprover.ProcessRequest(request);
        }
        else
        {
            Console.WriteLine($"请求 {request.RequestId} 无法批准,没有足够权限的审批人");
        }
    }
}

// 具体处理者 - 副总裁
public class VicePresident : Approver
{
    public VicePresident(string name) : base(name)
    {
    }
    
    public override void ProcessRequest(PurchaseRequest request)
    {
        if (request.Amount <= 100000.0)
        {
            Console.WriteLine($"{_name} 副总裁批准了采购请求 {request.RequestId}: {request.Description}, 金额: ${request.Amount}");
        }
        else if (_nextApprover != null)
        {
            Console.WriteLine($"{_name} 副总裁无权批准 ${request.Amount} 的请求,转交给上级");
            _nextApprover.ProcessRequest(request);
        }
        else
        {
            Console.WriteLine($"请求 {request.RequestId} 无法批准,没有足够权限的审批人");
        }
    }
}

// 具体处理者 - 总裁
public class President : Approver
{
    public President(string name) : base(name)
    {
    }
    
    public override void ProcessRequest(PurchaseRequest request)
    {
        if (request.Amount <= 500000.0)
        {
            Console.WriteLine($"{_name} 总裁批准了采购请求 {request.RequestId}: {request.Description}, 金额: ${request.Amount}");
        }
        else
        {
            Console.WriteLine($"{_name} 总裁也无法批准 ${request.Amount} 的请求,需要董事会审批");
        }
    }
}

// 客户端代码
public class Client
{
    public static void Main()
    {
        // 创建审批人
        Approver jerry = new DepartmentManager("Jerry");
        Approver robert = new Director("Robert");
        Approver mike = new VicePresident("Mike");
        Approver john = new President("John");
        
        // 设置责任链
        jerry.SetNext(robert);
        robert.SetNext(mike);
        mike.SetNext(john);
        
        // 创建采购请求
        PurchaseRequest request1 = new PurchaseRequest("PR-001", "办公用品", 8500.0);
        PurchaseRequest request2 = new PurchaseRequest("PR-002", "服务器设备", 35000.0);
        PurchaseRequest request3 = new PurchaseRequest("PR-003", "公司年会", 85000.0);
        PurchaseRequest request4 = new PurchaseRequest("PR-004", "新办公楼装修", 380000.0);
        PurchaseRequest request5 = new PurchaseRequest("PR-005", "企业收购", 1200000.0);
        
        // 处理请求
        Console.WriteLine("=== 处理采购请求 ===");
        jerry.ProcessRequest(request1);
        jerry.ProcessRequest(request2);
        jerry.ProcessRequest(request3);
        jerry.ProcessRequest(request4);
        jerry.ProcessRequest(request5);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

复杂实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

// 1. 请求类 - 包含更多元数据
public class ExpenseRequest
{
    public string RequestId { get; }
    public string EmployeeId { get; }
    public string EmployeeName { get; }
    public string Department { get; }
    public string Description { get; }
    public decimal Amount { get; }
    public ExpenseCategory Category { get; }
    public DateTime SubmissionDate { get; }
    public List<string> Attachments { get; }
    public Dictionary<string, string> AdditionalInfo { get; }
    public ExpenseStatus Status { get; set; }
    public List<ApprovalRecord> ApprovalHistory { get; }
    
    public ExpenseRequest(
        string employeeId,
        string employeeName,
        string department,
        string description,
        decimal amount,
        ExpenseCategory category)
    {
        RequestId = "EXP-" + Guid.NewGuid().ToString().Substring(0, 8).ToUpper();
        EmployeeId = employeeId;
        EmployeeName = employeeName;
        Department = department;
        Description = description;
        Amount = amount;
        Category = category;
        SubmissionDate = DateTime.Now;
        Attachments = new List<string>();
        AdditionalInfo = new Dictionary<string, string>();
        Status = ExpenseStatus.Submitted;
        ApprovalHistory = new List<ApprovalRecord>();
    }
    
    public void AddAttachment(string fileUrl)
    {
        Attachments.Add(fileUrl);
    }
    
    public void AddAdditionalInfo(string key, string value)
    {
        AdditionalInfo[key] = value;
    }
    
    public void AddApprovalRecord(ApprovalRecord record)
    {
        ApprovalHistory.Add(record);
        Status = record.Decision;
    }
    
    public override string ToString()
    {
        return $"请求: {RequestId}, 员工: {EmployeeName} ({EmployeeId}), 金额: ${Amount}, 类别: {Category}, 状态: {Status}";
    }
}

// 2. 审批记录
public class ApprovalRecord
{
    public string ApproverId { get; }
    public string ApproverName { get; }
    public string ApproverRole { get; }
    public DateTime DecisionDate { get; }
    public ExpenseStatus Decision { get; }
    public string Comments { get; }
    
    public ApprovalRecord(
        string approverId,
        string approverName,
        string approverRole,
        ExpenseStatus decision,
        string comments)
    {
        ApproverId = approverId;
        ApproverName = approverName;
        ApproverRole = approverRole;
        DecisionDate = DateTime.Now;
        Decision = decision;
        Comments = comments;
    }
    
    public override string ToString()
    {
        return $"{DecisionDate:yyyy-MM-dd HH:mm}: {ApproverName} ({ApproverRole}) - {Decision} - {Comments}";
    }
}

// 3. 枚举类型
public enum ExpenseCategory
{
    Travel,
    Meals,
    Accommodation,
    Office,
    Equipment,
    Training,
    Software,
    Other
}

public enum ExpenseStatus
{
    Submitted,
    ApprovedByManager,
    ApprovedByDirector,
    ApprovedByVP,
    ApprovedByCFO,
    Rejected,
    NeedMoreInfo,
    Canceled
}

// 4. 处理结果
public class ApprovalResult
{
    public bool IsProcessed { get; }
    public ExpenseStatus Status { get; }
    public string Comments { get; }
    public string ProcessedBy { get; }
    
    public ApprovalResult(bool isProcessed, ExpenseStatus status, string comments, string processedBy)
    {
        IsProcessed = isProcessed;
        Status = status;
        Comments = comments;
        ProcessedBy = processedBy;
    }
    
    public static ApprovalResult NotProcessed()
    {
        return new ApprovalResult(false, ExpenseStatus.Submitted, null, null);
    }
}

// 5. 抽象处理者
public abstract class ExpenseHandler
{
    protected ExpenseHandler _nextHandler;
    protected string _handlerId;
    protected string _handlerName;
    protected string _role;
    
    public ExpenseHandler(string handlerId, string handlerName, string role)
    {
        _handlerId = handlerId;
        _handlerName = handlerName;
        _role = role;
    }
    
    public ExpenseHandler SetNext(ExpenseHandler nextHandler)
    {
        _nextHandler = nextHandler;
        return nextHandler; // 返回下一个处理者,便于链式调用
    }
    
    public virtual async Task<ApprovalResult> HandleRequest(ExpenseRequest request)
    {
        if (CanHandle(request))
        {
            return await ProcessRequest(request);
        }
        else if (_nextHandler != null)
        {
            Console.WriteLine($"{_handlerName} ({_role}) 无权处理此请求,转交给 {_nextHandler._handlerName}");
            return await _nextHandler.HandleRequest(request);
        }
        else
        {
            Console.WriteLine($"请求 {request.RequestId} 无法处理,没有合适的处理者");
            return ApprovalResult.NotProcessed();
        }
    }
    
    protected abstract bool CanHandle(ExpenseRequest request);
    protected abstract Task<ApprovalResult> ProcessRequest(ExpenseRequest request);
    
    protected ApprovalRecord CreateApprovalRecord(ExpenseStatus decision, string comments)
    {
        return new ApprovalRecord(
            _handlerId,
            _handlerName,
            _role,
            decision,
            comments
        );
    }
}

// 6. 具体处理者 - 直接经理
public class ManagerHandler : ExpenseHandler
{
    private readonly decimal _approvalLimit;
    
    public ManagerHandler(string handlerId, string handlerName, decimal approvalLimit = 5000m)
        : base(handlerId, handlerName, "Department Manager")
    {
        _approvalLimit = approvalLimit;
    }
    
    protected override bool CanHandle(ExpenseRequest request)
    {
        return request.Amount <= _approvalLimit;
    }
    
    protected override async Task<ApprovalResult> ProcessRequest(ExpenseRequest request)
    {
        // 模拟处理时间
        await Task.Delay(500);
        
        Console.WriteLine($"{_handlerName} ({_role}) 正在审批 {request.RequestId}");
        
        // 根据类别做一些特殊处理
        if (request.Category == ExpenseCategory.Meals && request.Amount > 1000)
        {
            // 餐饮费超过1000需要特别审查
            Console.WriteLine($"{_handlerName} 要求提供餐饮费的详细说明和参与者名单");
            
            var record = CreateApprovalRecord(
                ExpenseStatus.NeedMoreInfo,
                "餐饮费超过$1000,请提供详细说明和参与者名单"
            );
            
            request.AddApprovalRecord(record);
            
            return new ApprovalResult(
                true,
                ExpenseStatus.NeedMoreInfo,
                "餐饮费超过$1000,请提供详细说明和参与者名单",
                _handlerName
            );
        }
        
        // 正常审批
        Console.WriteLine($"{_handlerName} ({_role}) 批准了请求 {request.RequestId}: {request.Description}, 金额: ${request.Amount}");
        
        var approvalRecord = CreateApprovalRecord(
            ExpenseStatus.ApprovedByManager,
            $"已批准,金额在部门经理 ${_approvalLimit} 权限范围内"
        );
        
        request.AddApprovalRecord(approvalRecord);
        
        return new ApprovalResult(
            true,
            ExpenseStatus.ApprovedByManager,
            $"已批准,金额在部门经理 ${_approvalLimit} 权限范围内",
            _handlerName
        );
    }
}

// 7. 具体处理者 - 总监
public class DirectorHandler : ExpenseHandler
{
    private readonly decimal _approvalLimit;
    
    public DirectorHandler(string handlerId, string handlerName, decimal approvalLimit = 20000m)
        : base(handlerId, handlerName, "Director")
    {
        _approvalLimit = approvalLimit;
    }
    
    protected override bool CanHandle(ExpenseRequest request)
    {
        return request.Amount <= _approvalLimit;
    }
    
    protected override async Task<ApprovalResult> ProcessRequest(ExpenseRequest request)
    {
        // 模拟处理时间
        await Task.Delay(800);
        
        Console.WriteLine($"{_handlerName} ({_role}) 正在审批 {request.RequestId}");
        
        // 特殊类别的审批
        if (request.Category == ExpenseCategory.Equipment && !request.Attachments.Any())
        {
            Console.WriteLine($"{_handlerName} 拒绝了请求,设备采购需要提供报价单");
            
            var record = CreateApprovalRecord(
                ExpenseStatus.Rejected,
                "设备采购必须提供至少一份报价单附件"
            );
            
            request.AddApprovalRecord(record);
            
            return new ApprovalResult(
                true,
                ExpenseStatus.Rejected,
                "设备采购必须提供至少一份报价单附件",
                _handlerName
            );
        }
        
        // 正常审批
        Console.WriteLine($"{_handlerName} ({_role}) 批准了请求 {request.RequestId}: {request.Description}, 金额: ${request.Amount}");
        
        var approvalRecord = CreateApprovalRecord(
            ExpenseStatus.ApprovedByDirector,
            $"已批准,金额在总监 ${_approvalLimit} 权限范围内"
        );
        
        request.AddApprovalRecord(approvalRecord);
        
        return new ApprovalResult(
            true,
            ExpenseStatus.ApprovedByDirector,
            $"已批准,金额在总监 ${_approvalLimit} 权限范围内",
            _handlerName
        );
    }
}

// 8. 具体处理者 - 副总裁
public class VicePresidentHandler : ExpenseHandler
{
    private readonly decimal _approvalLimit;
    
    public VicePresidentHandler(string handlerId, string handlerName, decimal approvalLimit = 100000m)
        : base(handlerId, handlerName, "Vice President")
    {
        _approvalLimit = approvalLimit;
    }
    
    protected override bool CanHandle(ExpenseRequest request)
    {
        return request.Amount <= _approvalLimit;
    }
    
    protected override async Task<ApprovalResult> ProcessRequest(ExpenseRequest request)
    {
        // 模拟处理时间
        await Task.Delay(1000);
        
        Console.WriteLine($"{_handlerName} ({_role}) 正在审批 {request.RequestId}");
        
        // 针对大额请求的特殊处理
        if (request.Amount > 50000)
        {
            // 大额请求需要额外检查是否有足够的预算
            bool hasBudget = CheckDepartmentBudget(request.Department, request.Amount);
            
            if (!hasBudget)
            {
                Console.WriteLine($"{_handlerName} 拒绝了请求,部门预算不足");
                
                var record = CreateApprovalRecord(
                    ExpenseStatus.Rejected,
                    $"部门 {request.Department} 预算不足,无法支持 ${request.Amount} 的支出"
                );
                
                request.AddApprovalRecord(record);
                
                return new ApprovalResult(
                    true,
                    ExpenseStatus.Rejected,
                    $"部门 {request.Department} 预算不足,无法支持 ${request.Amount} 的支出",
                    _handlerName
                );
            }
        }
        
        // 正常审批
        Console.WriteLine($"{_handlerName} ({_role}) 批准了请求 {request.RequestId}: {request.Description}, 金额: ${request.Amount}");
        
        var approvalRecord = CreateApprovalRecord(
            ExpenseStatus.ApprovedByVP,
            $"已批准,金额在副总裁 ${_approvalLimit} 权限范围内"
        );
        
        request.AddApprovalRecord(approvalRecord);
        
        return new ApprovalResult(
            true,
            ExpenseStatus.ApprovedByVP,
            $"已批准,金额在副总裁 ${_approvalLimit} 权限范围内",
            _handlerName
        );
    }
    
    private bool CheckDepartmentBudget(string department, decimal amount)
    {
        // 模拟预算检查
        // 在实际应用中,这里会查询财务系统
        Random random = new Random();
        return random.Next(0, 10) > 3; // 70% 的概率有足够预算
    }
}

// 9. 具体处理者 - 首席财务官(CFO)
public class CFOHandler : ExpenseHandler
{
    private readonly decimal _approvalLimit;
    
    public CFOHandler(string handlerId, string handlerName, decimal approvalLimit = 500000m)
        : base(handlerId, handlerName, "CFO")
    {
        _approvalLimit = approvalLimit;
    }
    
    protected override bool CanHandle(ExpenseRequest request)
    {
        return request.Amount <= _approvalLimit;
    }
    
    protected override async Task<ApprovalResult> ProcessRequest(ExpenseRequest request)
    {
        // 模拟处理时间
        await Task.Delay(1500);
        
        Console.WriteLine($"{_handlerName} ({_role}) 正在审批 {request.RequestId}");
        
        // CFO级别的请求需要财务部门审核
        bool financialReviewPassed = await PerformFinancialReview(request);
        
        if (!financialReviewPassed)
        {
            Console.WriteLine($"{_handlerName} 拒绝了请求,财务审核未通过");
            
            var record = CreateApprovalRecord(
                ExpenseStatus.Rejected,
                "财务审核未通过,需要额外的财务证明材料"
            );
            
            request.AddApprovalRecord(record);
            
            return new ApprovalResult(
                true,
                ExpenseStatus.Rejected,
                "财务审核未通过,需要额外的财务证明材料",
                _handlerName
            );
        }
        
        // 正常审批
        Console.WriteLine($"{_handlerName} ({_role}) 批准了请求 {request.RequestId}: {request.Description}, 金额: ${request.Amount}");
        
        var approvalRecord = CreateApprovalRecord(
            ExpenseStatus.ApprovedByCFO,
            $"已批准,金额在CFO ${_approvalLimit} 权限范围内,已通过财务审核"
        );
        
        request.AddApprovalRecord(approvalRecord);
        
        return new ApprovalResult(
            true,
            ExpenseStatus.ApprovedByCFO,
            $"已批准,金额在CFO ${_approvalLimit} 权限范围内,已通过财务审核",
            _handlerName
        );
    }
    
    private async Task<bool> PerformFinancialReview(ExpenseRequest request)
    {
        // 模拟财务审核流程
        await Task.Delay(500);
        
        // 在实际应用中,这里会进行详细的财务审核
        Console.WriteLine($"为请求 {request.RequestId} 执行财务审核...");
        
        // 简单示例:超过200000的请求有30%的概率不通过审核
        if (request.Amount > 200000)
        {
            Random random = new Random();
            return random.Next(0, 10) > 3; // 70% 的概率通过审核
        }
        
        return true;
    }
}

// 10. 特殊处理者 - 合规检查
public class ComplianceHandler : ExpenseHandler
{
    public ComplianceHandler(string handlerId, string handlerName)
        : base(handlerId, handlerName, "Compliance Officer")
    {
    }
    
    protected override bool CanHandle(ExpenseRequest request)
    {
        // 合规检查处理所有请求
        return true;
    }
    
    protected override async Task<ApprovalResult> ProcessRequest(ExpenseRequest request)
    {
        // 模拟合规检查
        await Task.Delay(300);
        
        Console.WriteLine($"{_handlerName} ({_role}) 正在执行合规检查 {request.RequestId}");
        
        // 检查是否有任何合规问题
        bool hasComplianceIssue = CheckForComplianceIssues(request);
        
        if (hasComplianceIssue)
        {
            Console.WriteLine($"{_handlerName} 拒绝了请求,存在合规问题");
            
            var record = CreateApprovalRecord(
                ExpenseStatus.Rejected,
                "请求违反了公司合规政策,请查阅公司报销指南"
            );
            
            request.AddApprovalRecord(record);
            
            return new ApprovalResult(
                true,
                ExpenseStatus.Rejected,
                "请求违反了公司合规政策,请查阅公司报销指南",
                _handlerName
            );
        }
        
        // 通过合规检查,继续下一个处理者
        Console.WriteLine($"{_handlerName} 确认请求符合合规要求");
        
        if (_nextHandler != null)
        {
            return await _nextHandler.HandleRequest(request);
        }
        
        return ApprovalResult.NotProcessed();
    }
    
    private bool CheckForComplianceIssues(ExpenseRequest request)
    {
        // 检查一些合规问题
        
        // 1. 特定类别的请求需要有附件
        if ((request.Category == ExpenseCategory.Travel || 
             request.Category == ExpenseCategory.Equipment) && 
             !request.Attachments.Any())
        {
            return true; // 没有附件,存在合规问题
        }
        
        // 2. 检查是否有异常大的金额
        if (request.Amount > 10000 && request.Description.Length < 50)
        {
            return true; // 大额请求但描述不充分
        }
        
        // 在实际应用中,还会有更多合规检查
        return false;
    }
}

// 11. 特殊处理者 - 董事会
public class BoardOfDirectorsHandler : ExpenseHandler
{
    public BoardOfDirectorsHandler(string handlerId, string handlerName)
        : base(handlerId, handlerName, "Board of Directors")
    {
    }
    
    protected override bool CanHandle(ExpenseRequest request)
    {
        // 董事会处理所有请求
        return true;
    }
    
    protected override async Task<ApprovalResult> ProcessRequest(ExpenseRequest request)
    {
        // 模拟董事会审批流程,这通常需要时间
        await Task.Delay(3000);
        
        Console.WriteLine($"{_handlerName} ({_role}) 正在审批 {request.RequestId}");
        
        // 董事会需要特别会议来批准非常大的请求
        if (request.Amount > 1000000)
        {
            Console.WriteLine($"{_handlerName} 需要召开特别会议来审议这笔大额支出");
            
            // 模拟会议结果
            Random random = new Random();
            bool approved = random.Next(0, 10) > 3; // 70% 的概率获批
            
            if (approved)
            {
                Console.WriteLine($"{_handlerName} 批准了金额为 ${request.Amount} 的请求 {request.RequestId}");
                
                var record = CreateApprovalRecord(
                    ExpenseStatus.ApprovedByCFO, // 使用CFO审批状态,实际中可能有专门的董事会审批状态
                    "经董事会特别会议审议通过"
                );
                
                request.AddApprovalRecord(record);
                
                return new ApprovalResult(
                    true,
                    ExpenseStatus.ApprovedByCFO,
                    "经董事会特别会议审议通过",
                    _handlerName
                );
            }
            else
            {
                Console.WriteLine($"{_handlerName} 拒绝了金额为 ${request.Amount} 的请求 {request.RequestId}");
                
                var record = CreateApprovalRecord(
                    ExpenseStatus.Rejected,
                    "董事会认为当前财务状况不适合这笔大额支出"
                );
                
                request.AddApprovalRecord(record);
                
                return new ApprovalResult(
                    true,
                    ExpenseStatus.Rejected,
                    "董事会认为当前财务状况不适合这笔大额支出",
                    _handlerName
                );
            }
        }
        
        // 500,000 到 1,000,000 之间的请求可以由董事会直接批准
        Console.WriteLine($"{_handlerName} 批准了请求 {request.RequestId}: {request.Description}, 金额: ${request.Amount}");
        
        var approvalRecord = CreateApprovalRecord(
            ExpenseStatus.ApprovedByCFO, // 使用CFO审批状态,实际中可能有专门的董事会审批状态
            "董事会已批准这笔支出"
        );
        
        request.AddApprovalRecord(approvalRecord);
        
        return new ApprovalResult(
            true,
            ExpenseStatus.ApprovedByCFO,
            "董事会已批准这笔支出",
            _handlerName
        );
    }
}

// 12. 责任链构建器
public class ExpenseApprovalChainBuilder
{
    public static ExpenseHandler BuildStandardApprovalChain()
    {
        // 创建处理者
        var complianceOfficer = new ComplianceHandler("CO001", "Grace");
        var manager = new ManagerHandler("MGR001", "Bob", 5000m);
        var director = new DirectorHandler("DIR001", "Susan", 20000m);
        var vicePresident = new VicePresidentHandler("VP001", "Tom", 100000m);
        var cfo = new CFOHandler("CFO001", "Alice", 500000m);
        var board = new BoardOfDirectorsHandler("BOD001", "Board");
        
        // 构建责任链
        complianceOfficer.SetNext(manager)
                         .SetNext(director)
                         .SetNext(vicePresident)
                         .SetNext(cfo)
                         .SetNext(board);
        
        return complianceOfficer; // 返回链的起点
    }
    
    public static ExpenseHandler BuildChainWithoutCompliance()
    {
        // 创建处理者
        var manager = new ManagerHandler("MGR001", "Bob", 5000m);
        var director = new DirectorHandler("DIR001", "Susan", 20000m);
        var vicePresident = new VicePresidentHandler("VP001", "Tom", 100000m);
        var cfo = new CFOHandler("CFO001", "Alice", 500000m);
        var board = new BoardOfDirectorsHandler("BOD001", "Board");
        
        // 构建责任链
        manager.SetNext(director)
               .SetNext(vicePresident)
               .SetNext(cfo)
               .SetNext(board);
        
        return manager; // 返回链的起点
    }
    
    public static ExpenseHandler BuildCustomApprovalChain(List<ExpenseHandler> handlers)
    {
        if (handlers == null || handlers.Count == 0)
        {
            throw new ArgumentException("处理者列表不能为空");
        }
        
        // 构建链
        for (int i = 0; i < handlers.Count - 1; i++)
        {
            handlers[i].SetNext(handlers[i + 1]);
        }
        
        return handlers[0]; // 返回链的起点
    }
}

// 13. 示例使用
public class ExpenseApprovalSystem
{
    private readonly ExpenseHandler _approvalChain;
    
    public ExpenseApprovalSystem(ExpenseHandler approvalChain)
    {
        _approvalChain = approvalChain;
    }
    
    public async Task<ApprovalResult> SubmitExpenseRequest(ExpenseRequest request)
    {
        Console.WriteLine($"提交支出请求: {request}");
        
        // 发送请求到责任链
        var result = await _approvalChain.HandleRequest(request);
        
        // 记录结果
        if (result.IsProcessed)
        {
            Console.WriteLine($"请求 {request.RequestId} 处理结果: {result.Status} - {result.Comments} (由 {result.ProcessedBy} 处理)");
        }
        else
        {
            Console.WriteLine($"请求 {request.RequestId} 未被处理");
        }
        
        return result;
    }
    
    public void PrintApprovalHistory(ExpenseRequest request)
    {
        Console.WriteLine($"\n=== 请求 {request.RequestId} 的审批历史 ===");
        Console.WriteLine($"状态: {request.Status}");
        
        if (request.ApprovalHistory.Count == 0)
        {
            Console.WriteLine("无审批记录");
            return;
        }
        
        foreach (var record in request.ApprovalHistory)
        {
            Console.WriteLine(record);
        }
    }
}

// 14. 客户端代码
public class Client
{
    public static async Task Main()
    {
        // 构建标准审批链
        var approvalChain = ExpenseApprovalChainBuilder.BuildStandardApprovalChain();
        
        // 创建审批系统
        var approvalSystem = new ExpenseApprovalSystem(approvalChain);
        
        // 创建几个示例请求
        var requests = CreateSampleRequests();
        
        // 处理每个请求
        foreach (var request in requests)
        {
            Console.WriteLine("\n========================================");
            var result = await approvalSystem.SubmitExpenseRequest(request);
            
            // 打印审批历史
            approvalSystem.PrintApprovalHistory(request);
            
            Console.WriteLine("========================================\n");
        }
    }
    
    private static List<ExpenseRequest> CreateSampleRequests()
    {
        var requests = new List<ExpenseRequest>();
        
        // 1. 小额办公用品请求
        var request1 = new ExpenseRequest(
            "EMP001",
            "John Smith",
            "IT",
            "办公用品",
            3500m,
            ExpenseCategory.Office
        );
        request1.AddAttachment("http://example.com/receipts/r001.pdf");
        requests.Add(request1);
        
        // 2. 中等金额的设备请求 - 无附件,应该被拒绝
        var request2 = new ExpenseRequest(
            "EMP002",
            "Emily Johnson",
            "Marketing",
            "新摄影设备",
            18000m,
            ExpenseCategory.Equipment
        );
        requests.Add(request2);
        
        // 3. 中等金额的设备请求 - 有附件
        var request3 = new ExpenseRequest(
            "EMP002",
            "Emily Johnson",
            "Marketing",
            "新摄影设备",
            18000m,
            ExpenseCategory.Equipment
        );
        request3.AddAttachment("http://example.com/quotes/q001.pdf");
        requests.Add(request3);
        
        // 4. 大额请求 - 需要副总裁审批
        var request4 = new ExpenseRequest(
            "EMP003",
            "Michael Brown",
            "Sales",
            "销售团队年度活动",
            75000m,
            ExpenseCategory.Other
        );
        request4.AddAttachment("http://example.com/proposals/p001.pdf");
        request4.AddAdditionalInfo("Participants", "150人");
        request4.AddAdditionalInfo("Duration", "3天");
        requests.Add(request4);
        
        // 5. 更大额请求 - 需要CFO审批
        var request5 = new ExpenseRequest(
            "EMP004",
            "Jessica Williams",
            "Operations",
            "仓库设备更新",
            350000m,
            ExpenseCategory.Equipment
        );
        request5.AddAttachment("http://example.com/quotes/q002.pdf");
        request5.AddAttachment("http://example.com/specs/s001.pdf");
        requests.Add(request5);
        
        // 6. 超大额请求 - 需要董事会审批
        var request6 = new ExpenseRequest(
            "EMP005",
            "Robert Taylor",
            "Executive",
            "新办公大楼装修",
            2500000m,
            ExpenseCategory.Other
        );
        request6.AddAttachment("http://example.com/plans/plan001.pdf");
        request6.AddAttachment("http://example.com/quotes/q003.pdf");
        request6.AddAdditionalInfo("Timeline", "6个月");
        request6.AddAdditionalInfo("Contractor", "ABC Construction");
        requests.Add(request6);
        
        return requests;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861

业务场景结合:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;

// 客户贷款申请系统 - 使用责任链模式处理贷款审批流程

// 1. 贷款申请类
public class LoanApplication
{
    public string ApplicationId { get; }
    public string CustomerId { get; set; }
    public string CustomerName { get; set; }
    public decimal RequestedAmount { get; set; }
    public int RequestedTermMonths { get; set; }
    public LoanPurpose Purpose { get; set; }
    public decimal AnnualIncome { get; set; }
    public decimal ExistingDebts { get; set; }
    public int CreditScore { get; set; }
    public DateTime ApplicationDate { get; set; }
    public LoanApplicationStatus Status { get; set; }
    public string AssignedOfficer { get; set; }
    public List<string> SupportingDocuments { get; set; }
    public Dictionary<string, string> AdditionalInfo { get; set; }
    public List<ProcessingRecord> ProcessingHistory { get; set; }
    
    public LoanApplication(string customerId, string customerName, decimal requestedAmount, 
        int requestedTermMonths, LoanPurpose purpose)
    {
        ApplicationId = "LOAN-" + Guid.NewGuid().ToString().Substring(0, 8).ToUpper();
        CustomerId = customerId;
        CustomerName = customerName;
        RequestedAmount = requestedAmount;
        RequestedTermMonths = requestedTermMonths;
        Purpose = purpose;
        ApplicationDate = DateTime.Now;
        Status = LoanApplicationStatus.Submitted;
        SupportingDocuments = new List<string>();
        AdditionalInfo = new Dictionary<string, string>();
        ProcessingHistory = new List<ProcessingRecord>();
    }
    
    public void AddSupportingDocument(string documentPath)
    {
        SupportingDocuments.Add(documentPath);
    }
    
    public void AddAdditionalInfo(string key, string value)
    {
        AdditionalInfo[key] = value;
    }
    
    public void AddProcessingRecord(ProcessingRecord record)
    {
        ProcessingHistory.Add(record);
        Status = record.NewStatus;
    }
    
    public decimal GetDebtToIncomeRatio()
    {
        if (AnnualIncome <= 0)
            return decimal.MaxValue;
            
        // 月收入
        decimal monthlyIncome = AnnualIncome / 12;
        
        // 月债务
        decimal monthlyDebt = CalculateMonthlyDebt();
        
        // 新贷款的月还款
        decimal estimatedMonthlyPayment = CalculateEstimatedMonthlyPayment();
        
        // 债务收入比
        return (monthlyDebt + estimatedMonthlyPayment) / monthlyIncome;
    }
    
    private decimal CalculateMonthlyDebt()
    {
        // 简化计算,假设现有债务按年利率5%计算月还款
        if (ExistingDebts <= 0)
            return 0;
            
        decimal monthlyInterestRate = 0.05m / 12;
        int termMonths = 60; // 假设5年
        
        return ExistingDebts * monthlyInterestRate * (decimal)Math.Pow((double)(1 + monthlyInterestRate), termMonths) / 
               ((decimal)Math.Pow((double)(1 + monthlyInterestRate), termMonths) - 1);
    }
    
    public decimal CalculateEstimatedMonthlyPayment()
    {
        if (RequestedAmount <= 0 || RequestedTermMonths <= 0)
            return 0;
            
        // 假设按年利率4.5%计算
        decimal monthlyInterestRate = 0.045m / 12;
        
        return RequestedAmount * monthlyInterestRate * (decimal)Math.Pow((double)(1 + monthlyInterestRate), RequestedTermMonths) / 
               ((decimal)Math.Pow((double)(1 + monthlyInterestRate), RequestedTermMonths) - 1);
    }
    
    public decimal CalculateLoanToValueRatio(decimal collateralValue)
    {
        if (collateralValue <= 0)
            return decimal.MaxValue;
            
        return RequestedAmount / collateralValue;
    }
    
    public override string ToString()
    {
        return $"申请ID: {ApplicationId}, 客户: {CustomerName}, 金额: ${RequestedAmount:N0}, 期限: {RequestedTermMonths}个月, 目的: {Purpose}, 状态: {Status}";
    }
}

// 2. 处理记录类
public class ProcessingRecord
{
    public string ProcessorId { get; }
    public string ProcessorName { get; }
    public string Role { get; }
    public DateTime ProcessingDate { get; }
    public LoanApplicationStatus PreviousStatus { get; }
    public LoanApplicationStatus NewStatus { get; }
    public string Comments { get; }
    
    public ProcessingRecord(
        string processorId,
        string processorName,
        string role,
        LoanApplicationStatus previousStatus,
        LoanApplicationStatus newStatus,
        string comments)
    {
        ProcessorId = processorId;
        ProcessorName = processorName;
        Role = role;
        ProcessingDate = DateTime.Now;
        PreviousStatus = previousStatus;
        NewStatus = newStatus;
        Comments = comments;
    }
    
    public override string ToString()
    {
        return $"{ProcessingDate:yyyy-MM-dd HH:mm}: {ProcessorName} ({Role}) - {PreviousStatus} -> {NewStatus} - {Comments}";
    }
}

// 3. 枚举类型
public enum LoanPurpose
{
    HomePurchase,
    HomeRefinance,
    HomeImprovement,
    PersonalLoan,
    AutoLoan,
    BusinessLoan,
    EducationLoan,
    Other
}

public enum LoanApplicationStatus
{
    Submitted,
    DocumentationReview,
    IncompleteDocumentation,
    DocumentationComplete,
    InInitialReview,
    CreditCheckPassed,
    CreditCheckFailed,
    IncomeVerificationPassed,
    IncomeVerificationFailed,
    UnderwritingReview,
    ApprovedByUnderwriter,
    RejectedByUnderwriter,
    PendingFinalApproval,
    Approved,
    Rejected,
    Withdrawn,
    Funded,
    Closed
}

// 4. 处理结果类
public class ProcessingResult
{
    public bool IsProcessed { get; }
    public LoanApplicationStatus Status { get; }
    public string ProcessorName { get; }
    public string Comments { get; }
    
    public ProcessingResult(bool isProcessed, LoanApplicationStatus status, string processorName, string comments)
    {
        IsProcessed = isProcessed;
        Status = status;
        ProcessorName = processorName;
        Comments = comments;
    }
    
    public static ProcessingResult NotProcessed()
    {
        return new ProcessingResult(false, LoanApplicationStatus.Submitted, null, "申请未处理");
    }
}

// 5. 处理者抽象类
public abstract class LoanProcessingHandler
{
    protected LoanProcessingHandler _nextHandler;
    protected string _handlerId;
    protected string _handlerName;
    protected string _role;
    protected ILogger _logger;
    
    public LoanProcessingHandler(string handlerId, string handlerName, string role, ILogger logger)
    {
        _handlerId = handlerId;
        _handlerName = handlerName;
        _role = role;
        _logger = logger;
    }
    
    public LoanProcessingHandler SetNext(LoanProcessingHandler nextHandler)
    {
        _nextHandler = nextHandler;
        return nextHandler; // 支持链式设置
    }
    
    public virtual async Task<ProcessingResult> ProcessRequest(LoanApplication application)
    {
        if (CanProcess(application))
        {
            return await HandleProcessing(application);
        }
        else if (_nextHandler != null)
        {
            _logger.LogInformation("{Handler} ({Role}) 将申请 {ApplicationId} 转交给 {NextHandler}",
                _handlerName, _role, application.ApplicationId, _nextHandler._handlerName);
            return await _nextHandler.ProcessRequest(application);
        }
        else
        {
            _logger.LogWarning("申请 {ApplicationId} 无法处理,没有合适的处理者", application.ApplicationId);
            return ProcessingResult.NotProcessed();
        }
    }
    
    protected abstract bool CanProcess(LoanApplication application);
    protected abstract Task<ProcessingResult> HandleProcessing(LoanApplication application);
    
    protected ProcessingRecord CreateProcessingRecord(LoanApplication application, LoanApplicationStatus newStatus, string comments)
    {
        return new ProcessingRecord(
            _handlerId,
            _handlerName,
            _role,
            application.Status,
            newStatus,
            comments
        );
    }
}

// 6. 文档验证处理者
public class DocumentationHandler : LoanProcessingHandler
{
    private readonly List<string> _requiredDocuments;
    
    public DocumentationHandler(string handlerId, string handlerName, ILogger logger)
        : base(handlerId, handlerName, "文档审核员", logger)
    {
        // 根据不同贷款类型设置所需文档
        _requiredDocuments = new List<string>
        {
            "身份证明",
            "收入证明",
            "银行账单",
            "贷款申请表"
        };
    }
    
    protected override bool CanProcess(LoanApplication application)
    {
        // 只处理刚提交或文档不完整的申请
        return application.Status == LoanApplicationStatus.Submitted || 
               application.Status == LoanApplicationStatus.IncompleteDocumentation;
    }
    
    protected override async Task<ProcessingResult> HandleProcessing(LoanApplication application)
    {
        _logger.LogInformation("{Handler} 正在审核申请 {ApplicationId} 的文档", _handlerName, application.ApplicationId);
        
        // 模拟处理时间
        await Task.Delay(300);
        
        // 更新状态为文档审核中
        var inReviewRecord = CreateProcessingRecord(
            application,
            LoanApplicationStatus.DocumentationReview,
            "开始文档审核"
        );
        application.AddProcessingRecord(inReviewRecord);
        
        // 检查是否提供了所有必需文档
        List<string> missingDocuments = GetMissingDocuments(application);
        
        if (missingDocuments.Count > 0)
        {
            _logger.LogInformation("申请 {ApplicationId} 缺少必要文档: {MissingDocs}", 
                application.ApplicationId, string.Join(", ", missingDocuments));
                
            var incompleteRecord = CreateProcessingRecord(
                application,
                LoanApplicationStatus.IncompleteDocumentation,
                $"文档不完整,缺少: {string.Join(", ", missingDocuments)}"
            );
            application.AddProcessingRecord(incompleteRecord);
            
            return new ProcessingResult(
                true,
                LoanApplicationStatus.IncompleteDocumentation,
                _handlerName,
                $"文档不完整,缺少: {string.Join(", ", missingDocuments)}"
            );
        }
        
        // 检查贷款目的特定的文档
        if (application.Purpose == LoanPurpose.HomeImprovement || 
            application.Purpose == LoanPurpose.HomeRefinance)
        {
            bool hasPropertyDocuments = application.SupportingDocuments.Any(d => d.Contains("房产证明"));
            
            if (!hasPropertyDocuments)
            {
                _logger.LogInformation("申请 {ApplicationId} 缺少房产相关文档", application.ApplicationId);
                
                var incompleteRecord = CreateProcessingRecord(
                    application,
                    LoanApplicationStatus.IncompleteDocumentation,
                    "缺少房产相关文档"
                );
                application.AddProcessingRecord(incompleteRecord);
                
                return new ProcessingResult(
                    true,
                    LoanApplicationStatus.IncompleteDocumentation,
                    _handlerName,
                    "缺少房产相关文档"
                );
            }
        }
        
        // 文档齐全,更新状态
        _logger.LogInformation("申请 {ApplicationId} 文档完整,准备进入初审", application.ApplicationId);
        
        var completeRecord = CreateProcessingRecord(
            application,
            LoanApplicationStatus.DocumentationComplete,
            "文档审核完成,所有必要文档已提供"
        );
        application.AddProcessingRecord(completeRecord);
        
        return new ProcessingResult(
            true,
            LoanApplicationStatus.DocumentationComplete,
            _handlerName,
            "文档审核完成,所有必要文档已提供"
        );
    }
    
    private List<string> GetMissingDocuments(LoanApplication application)
    {
        // 获取缺少的必需文档
        List<string> missingDocs = new List<string>();
        
        // 模拟检查文档
        foreach (string requiredDoc in _requiredDocuments)
        {
            bool hasDocument = application.SupportingDocuments.Any(d => d.Contains(requiredDoc));
            
            if (!hasDocument)
            {
                missingDocs.Add(requiredDoc);
            }
        }
        
        // 根据贷款目的添加特定要求
        if (application.Purpose == LoanPurpose.BusinessLoan)
        {
            bool hasBusinessPlan = application.SupportingDocuments.Any(d => d.Contains("商业计划"));
            
            if (!hasBusinessPlan)
            {
                missingDocs.Add("商业计划");
            }
        }
        
        return missingDocs;
    }
}

// 7. 信用审查处理者
public class CreditCheckHandler : LoanProcessingHandler
{
    private readonly int _minimumCreditScore;
    
    public CreditCheckHandler(string handlerId, string handlerName, ILogger logger, int minimumCreditScore = 600)
        : base(handlerId, handlerName, "信用审核员", logger)
    {
        _minimumCreditScore = minimumCreditScore;
    }
    
    protected override bool CanProcess(LoanApplication application)
    {
        // 只处理文档完整的申请
        return application.Status == LoanApplicationStatus.DocumentationComplete;
    }
    
    protected override async Task<ProcessingResult> HandleProcessing(LoanApplication application)
    {
        _logger.LogInformation("{Handler} 正在审核申请 {ApplicationId} 的信用状况", 
            _handlerName, application.ApplicationId);
            
        // 更新状态为初审中
        var initialReviewRecord = CreateProcessingRecord(
            application,
            LoanApplicationStatus.InInitialReview,
            "开始初审"
        );
        application.AddProcessingRecord(initialReviewRecord);
        
        // 模拟获取信用评分
        await Task.Delay(500);
        
        // 假设信用评分已经填充到申请中
        // 在实际应用中,这里可能会调用信用局API获取信用报告
        
        _logger.LogInformation("申请 {ApplicationId} 的信用评分: {CreditScore}", 
            application.ApplicationId, application.CreditScore);
            
        // 检查信用评分是否达到最低要求
        if (application.CreditScore < _minimumCreditScore)
        {
            _logger.LogInformation("申请 {ApplicationId} 信用评分不足,最低要求: {MinScore}", 
                application.ApplicationId, _minimumCreditScore);
                
            var failedRecord = CreateProcessingRecord(
                application,
                LoanApplicationStatus.CreditCheckFailed,
                $"信用评分 {application.CreditScore} 低于最低要求 {_minimumCreditScore}"
            );
            application.AddProcessingRecord(failedRecord);
            
            return new ProcessingResult(
                true,
                LoanApplicationStatus.CreditCheckFailed,
                _handlerName,
                $"信用评分 {application.CreditScore} 低于最低要求 {_minimumCreditScore}"
            );
        }
        
        // 信用评分通过
        _logger.LogInformation("申请 {ApplicationId} 通过信用评分检查", application.ApplicationId);
        
        var passedRecord = CreateProcessingRecord(
            application,
            LoanApplicationStatus.CreditCheckPassed,
            $"信用评分 {application.CreditScore} 满足要求"
        );
        application.AddProcessingRecord(passedRecord);
        
        // 继续下一步处理
        if (_nextHandler != null)
        {
            return await _nextHandler.ProcessRequest(application);
        }
        
        return new ProcessingResult(
            true,
            LoanApplicationStatus.CreditCheckPassed,
            _handlerName,
            $"信用评分 {application.CreditScore} 满足要求"
        );
    }
}

// 8. 收入验证处理者
public class IncomeVerificationHandler : LoanProcessingHandler
{
    private readonly decimal _maxDebtToIncomeRatio;
    
    public IncomeVerificationHandler(string handlerId, string handlerName, ILogger logger, decimal maxDebtToIncomeRatio = 0.43m)
        : base(handlerId, handlerName, "收入验证员", logger)
    {
        _maxDebtToIncomeRatio = maxDebtToIncomeRatio;
    }
    
    protected override bool CanProcess(LoanApplication application)
    {
        // 只处理已通过信用检查的申请
        return application.Status == LoanApplicationStatus.CreditCheckPassed;
    }
    
    protected override async Task<ProcessingResult> HandleProcessing(LoanApplication application)
    {
        _logger.LogInformation("{Handler} 正在验证申请 {ApplicationId} 的收入情况", 
            _handlerName, application.ApplicationId);
            
        // 模拟收入验证过程
        await Task.Delay(500);
        
        // 检查债务收入比
        decimal debtToIncomeRatio = application.GetDebtToIncomeRatio();
        
        _logger.LogInformation("申请 {ApplicationId} 的债务收入比: {DTI:P2}", 
            application.ApplicationId, debtToIncomeRatio);
            
        if (debtToIncomeRatio > _maxDebtToIncomeRatio)
        {
            _logger.LogInformation("申请 {ApplicationId} 的债务收入比过高,最大允许值: {MaxDTI:P2}", 
                application.ApplicationId, _maxDebtToIncomeRatio);
                
            var failedRecord = CreateProcessingRecord(
                application,
                LoanApplicationStatus.IncomeVerificationFailed,
                $"债务收入比 {debtToIncomeRatio:P2} 超过最大允许值 {_maxDebtToIncomeRatio:P2}"
            );
            application.AddProcessingRecord(failedRecord);
            
            return new ProcessingResult(
                true,
                LoanApplicationStatus.IncomeVerificationFailed,
                _handlerName,
                $"债务收入比 {debtToIncomeRatio:P2} 超过最大允许值 {_maxDebtToIncomeRatio:P2}"
            );
        }
        
        // 检查收入是否足以支付贷款
        decimal monthlyPayment = application.CalculateEstimatedMonthlyPayment();
        decimal monthlyIncome = application.AnnualIncome / 12;
        
        if (monthlyPayment > monthlyIncome * 0.28m) // 常见的前端比率标准
        {
            _logger.LogInformation("申请 {ApplicationId} 的贷款月供 {Payment:C} 占收入比例过高", 
                application.ApplicationId, monthlyPayment);
                
            var failedRecord = CreateProcessingRecord(
                application,
                LoanApplicationStatus.IncomeVerificationFailed,
                $"月供 {monthlyPayment:C} 超过月收入的28%,收入不足以支持此贷款"
            );
            application.AddProcessingRecord(failedRecord);
            
            return new ProcessingResult(
                true,
                LoanApplicationStatus.IncomeVerificationFailed,
                _handlerName,
                $"月供 {monthlyPayment:C} 超过月收入的28%,收入不足以支持此贷款"
            );
        }
        
        // 收入验证通过
        _logger.LogInformation("申请 {ApplicationId} 通过收入验证", application.ApplicationId);
        
        var passedRecord = CreateProcessingRecord(
            application,
            LoanApplicationStatus.IncomeVerificationPassed,
            $"债务收入比 {debtToIncomeRatio:P2} 在可接受范围内,月供能力充足"
        );
        application.AddProcessingRecord(passedRecord);
        
        // 继续下一步处理
        if (_nextHandler != null)
        {
            return await _nextHandler.ProcessRequest(application);
        }
        
        return new ProcessingResult(
            true,
            LoanApplicationStatus.IncomeVerificationPassed,
            _handlerName,
            $"债务收入比 {debtToIncomeRatio:P2} 在可接受范围内,月供能力充足"
        );
    }
}

// 9. 贷款审核员处理者
public class UnderwriterHandler : LoanProcessingHandler
{
    private readonly Dictionary<LoanPurpose, decimal> _loanToValueLimits;
    
    public UnderwriterHandler(string handlerId, string handlerName, ILogger logger)
        : base(handlerId, handlerName, "贷款审核员", logger)
    {
        // 设置不同贷款目的的贷款价值比限制
        _loanToValueLimits = new Dictionary<LoanPurpose, decimal>
        {
            { LoanPurpose.HomeImprovement, 0.90m },
            { LoanPurpose.HomeRefinance, 0.80m },
            { LoanPurpose.HomeRefinance, 0.85m },
            { LoanPurpose.AutoLoan, 0.95m },
            { LoanPurpose.BusinessLoan, 0.70m },
            { LoanPurpose.PersonalLoan, 1.00m }, // 无抵押贷款
            { LoanPurpose.EducationLoan, 1.00m }, // 无抵押贷款
            { LoanPurpose.Other, 0.75m }
        };
    }
    
    protected override bool CanProcess(LoanApplication application)
    {
        // 只处理已通过收入验证的申请
        return application.Status == LoanApplicationStatus.IncomeVerificationPassed;
    }
    
    protected override async Task<ProcessingResult> HandleProcessing(LoanApplication application)
    {
        _logger.LogInformation("{Handler} 正在审核申请 {ApplicationId}", 
            _handlerName, application.ApplicationId);
            
        // 更新状态为审核中
        var reviewRecord = CreateProcessingRecord(
            application,
            LoanApplicationStatus.UnderwritingReview,
            "开始贷款审核"
        );
        application.AddProcessingRecord(reviewRecord);
        
        // 模拟审核过程
        await Task.Delay(1000);
        
        // 进行综合审核
        bool approved = true;
        StringBuilder reasonBuilder = new StringBuilder();
        
        // 1. 检查贷款申请金额是否合理
        if (application.RequestedAmount > 10000000) // 1千万上限
        {
            approved = false;
            reasonBuilder.AppendLine("贷款金额超出银行最高限制");
        }
        
        // 2. 对于有抵押贷款,检查贷款价值比
        if (NeedsCollateral(application.Purpose))
        {
            // 在实际应用中,这个值应该从抵押品评估中获取
            decimal collateralValue = GetEstimatedCollateralValue(application);
            decimal loanToValueRatio = application.CalculateLoanToValueRatio(collateralValue);
            
            decimal maxLtv = _loanToValueLimits[application.Purpose];
            
            if (loanToValueRatio > maxLtv)
            {
                approved = false;
                reasonBuilder.AppendLine($"贷款价值比 {loanToValueRatio:P2} 超过允许的最大值 {maxLtv:P2}");
            }
        }
        
        // 3. 检查贷款期限是否合理
        if (application.RequestedTermMonths > 360) // 30年上限
        {
            approved = false;
            reasonBuilder.AppendLine("贷款期限超出最长允许期限(30年)");
        }
        
        // 4. 其他因素审核(简化)
        if (application.CreditScore < 680 && application.RequestedAmount > 500000)
        {
            // 信用分数低于680且贷款金额大,需要额外审查
            bool passesManualReview = await PerformManualReview(application);
            
            if (!passesManualReview)
            {
                approved = false;
                reasonBuilder.AppendLine("手动审核未通过,信用分数较低且贷款金额较大");
            }
        }
        
        // 最终审核决定
        if (approved)
        {
            _logger.LogInformation("申请 {ApplicationId} 通过贷款审核", application.ApplicationId);
            
            var approvedRecord = CreateProcessingRecord(
                application,
                LoanApplicationStatus.ApprovedByUnderwriter,
                "贷款审核通过,等待最终批准"
            );
            application.AddProcessingRecord(approvedRecord);
            
            return new ProcessingResult(
                true,
                LoanApplicationStatus.ApprovedByUnderwriter,
                _handlerName,
                "贷款审核通过,等待最终批准"
            );
        }
        else
        {
            _logger.LogInformation("申请 {ApplicationId} 未通过贷款审核: {Reasons}", 
                application.ApplicationId, reasonBuilder.ToString());
                
            var rejectedRecord = CreateProcessingRecord(
                application,
                LoanApplicationStatus.RejectedByUnderwriter,
                reasonBuilder.ToString()
            );
            application.AddProcessingRecord(rejectedRecord);
            
            return new ProcessingResult(
                true,
                LoanApplicationStatus.RejectedByUnderwriter,
                _handlerName,
                reasonBuilder.ToString()
            );
        }
    }
    
    private bool NeedsCollateral(LoanPurpose purpose)
    {
        return purpose == LoanPurpose.HomeImprovement ||
               purpose == LoanPurpose.HomeRefinance ||
               purpose == LoanPurpose.HomeRefinance ||
               purpose == LoanPurpose.AutoLoan ||
               purpose == LoanPurpose.BusinessLoan;
    }
    
    private decimal GetEstimatedCollateralValue(LoanApplication application)
    {
        // 在实际应用中,这个值应该从抵押品评估报告中获取
        // 这里简化为基于贷款金额的估计值
        
        switch (application.Purpose)
        {
            case LoanPurpose.HomeImprovement:
            case LoanPurpose.HomeRefinance:
            case LoanPurpose.HomeRefinance:
                // 假设房产价值是贷款额的1.5倍
                return application.RequestedAmount * 1.5m;
                
            case LoanPurpose.AutoLoan:
                // 假设车辆价值与贷款额相近
                return application.RequestedAmount * 1.1m;
                
            case LoanPurpose.BusinessLoan:
                // 假设商业抵押品价值是贷款额的2倍
                return application.RequestedAmount * 2.0m;
                
            default:
                // 无抵押贷款
                return 0;
        }
    }
    
    private async Task<bool> PerformManualReview(LoanApplication application)
    {
        // 模拟手动审核过程
        await Task.Delay(500);
        
        // 简化的逻辑,实际中会有更复杂的审核流程
        // 如果申请人收入高,即使信用分数较低也可能通过
        if (application.AnnualIncome > 200000)
        {
            return true;
        }
        
        // 如果申请人债务收入比较低,也可能通过
        if (application.GetDebtToIncomeRatio() < 0.3m)
        {
            return true;
        }
        
        // 其他情况,60%的概率通过
        Random random = new Random();
        return random.NextDouble() < 0.6;
    }
}

// 10. 最终审批处理者
public class FinalApprovalHandler : LoanProcessingHandler
{
    private readonly decimal _approvalLimit;
    
    public FinalApprovalHandler(string handlerId, string handlerName, string role, ILogger logger, decimal approvalLimit)
        : base(handlerId, handlerName, role, logger)
    {
        _approvalLimit = approvalLimit;
    }
    
    protected override bool CanProcess(LoanApplication application)
    {
        // 只处理已通过贷款审核的申请且在权限范围内
        return application.Status == LoanApplicationStatus.ApprovedByUnderwriter && 
               application.RequestedAmount <= _approvalLimit;
    }
    
    protected override async Task<ProcessingResult> HandleProcessing(LoanApplication application)
    {
        _logger.LogInformation("{Handler} ({Role}) 正在进行最终审批,申请 {ApplicationId}", 
            _handlerName, _role, application.ApplicationId);
            
        // 更新状态为等待最终审批
        var pendingRecord = CreateProcessingRecord(
            application,
            LoanApplicationStatus.PendingFinalApproval,
            "等待最终审批"
        );
        application.AddProcessingRecord(pendingRecord);
        
        // 模拟最终审批过程
        await Task.Delay(500);
        
        // 在权限范围内直接批准
        _logger.LogInformation("{Handler} ({Role}) 批准了申请 {ApplicationId}, 金额: ${Amount:N0}", 
            _handlerName, _role, application.ApplicationId, application.RequestedAmount);
            
        var approvedRecord = CreateProcessingRecord(
            application,
            LoanApplicationStatus.Approved,
            $"贷款已批准,金额: ${application.RequestedAmount:N0},期限: {application.RequestedTermMonths}个月"
        );
        application.AddProcessingRecord(approvedRecord);
        
        return new ProcessingResult(
            true,
            LoanApplicationStatus.Approved,
            _handlerName,
            $"贷款已批准,金额: ${application.RequestedAmount:N0},期限: {application.RequestedTermMonths}个月"
        );
    }
}

// 11. 高级审批处理者(处理大额贷款)
public class SeniorApprovalHandler : FinalApprovalHandler
{
    private readonly decimal _escalationLimit;
    
    public SeniorApprovalHandler(string handlerId, string handlerName, ILogger logger, decimal approvalLimit, decimal escalationLimit)
        : base(handlerId, handlerName, "高级贷款主管", logger, approvalLimit)
    {
        _escalationLimit = escalationLimit;
    }
    
    protected override bool CanProcess(LoanApplication application)
    {
        // 处理已通过贷款审核且金额在审批权限范围内的申请
        return application.Status == LoanApplicationStatus.ApprovedByUnderwriter && 
               application.RequestedAmount <= _approvalLimit;
    }
    
    protected override async Task<ProcessingResult> HandleProcessing(LoanApplication application)
    {
        // 对于超过上报限制的贷款,需要额外审查
        if (application.RequestedAmount > _escalationLimit)
        {
            _logger.LogInformation("{Handler} 需要额外审查申请 {ApplicationId},金额超过 ${Limit:N0}", 
                _handlerName, application.ApplicationId, _escalationLimit);
                
            // 执行额外的风险评估
            bool riskAssessmentPassed = await PerformRiskAssessment(application);
            
            if (!riskAssessmentPassed)
            {
                _logger.LogInformation("{Handler} 拒绝了申请 {ApplicationId},风险评估未通过", 
                    _handlerName, application.ApplicationId);
                    
                var rejectedRecord = CreateProcessingRecord(
                    application,
                    LoanApplicationStatus.Rejected,
                    "风险评估未通过,贷款申请被拒绝"
                );
                application.AddProcessingRecord(rejectedRecord);
                
                return new ProcessingResult(
                    true,
                    LoanApplicationStatus.Rejected,
                    _handlerName,
                    "风险评估未通过,贷款申请被拒绝"
                );
            }
        }
        
        // 通过基类处理常规审批流程
        return await base.HandleProcessing(application);
    }
    
    private async Task<bool> PerformRiskAssessment(LoanApplication application)
    {
        // 模拟风险评估流程
        await Task.Delay(1000);
        
        // 在实际应用中,这里会进行全面的风险评估
        
        // 简化的风险评估逻辑
        if (application.CreditScore < 720)
        {
            return false; // 大额贷款需要更高的信用分数
        }
        
        if (application.GetDebtToIncomeRatio() > 0.35m)
        {
            return false; // 大额贷款需要更低的债务收入比
        }
        
        // 80%的概率通过风险评估
        Random random = new Random();
        return random.NextDouble() < 0.8;
    }
}

// 12. 贷款委员会处理者(处理特大额贷款)
public class LoanCommitteeHandler : LoanProcessingHandler
{
    public LoanCommitteeHandler(string handlerId, string handlerName, ILogger logger)
        : base(handlerId, handlerName, "贷款委员会", logger)
    {
    }
    
    protected override bool CanProcess(LoanApplication application)
    {
        // 处理已通过贷款审核但超出高级审批权限的申请
        return application.Status == LoanApplicationStatus.ApprovedByUnderwriter || 
               application.Status == LoanApplicationStatus.PendingFinalApproval;
    }
    
    protected override async Task<ProcessingResult> HandleProcessing(LoanApplication application)
    {
        _logger.LogInformation("{Handler} 正在审议申请 {ApplicationId},金额: ${Amount:N0}", 
            _handlerName, application.ApplicationId, application.RequestedAmount);
            
        // 更新状态为等待委员会审批
        var pendingRecord = CreateProcessingRecord(
            application,
            LoanApplicationStatus.PendingFinalApproval,
            "等待贷款委员会审批"
        );
        application.AddProcessingRecord(pendingRecord);
        
        // 模拟委员会审议过程,这通常需要较长时间
        await Task.Delay(2000);
        
        // 委员会决策(简化)
        Random random = new Random();
        bool approved = random.NextDouble() < 0.7; // 70%的概率获批
        
        if (approved)
        {
            _logger.LogInformation("{Handler} 批准了申请 {ApplicationId}", 
                _handlerName, application.ApplicationId);
                
            var approvedRecord = CreateProcessingRecord(
                application,
                LoanApplicationStatus.Approved,
                "贷款委员会已批准此贷款申请"
            );
            application.AddProcessingRecord(approvedRecord);
            
            return new ProcessingResult(
                true,
                LoanApplicationStatus.Approved,
                _handlerName,
                "贷款委员会已批准此贷款申请"
            );
        }
        else
        {
            _logger.LogInformation("{Handler} 拒绝了申请 {ApplicationId}", 
                _handlerName, application.ApplicationId);
                
            var rejectedRecord = CreateProcessingRecord(
                application,
                LoanApplicationStatus.Rejected,
                "贷款委员会认为此贷款风险过高,申请被拒绝"
            );
            application.AddProcessingRecord(rejectedRecord);
            
            return new ProcessingResult(
                true,
                LoanApplicationStatus.Rejected,
                _handlerName,
                "贷款委员会认为此贷款风险过高,申请被拒绝"
            );
        }
    }
}

// 13. 责任链构建器
public class LoanProcessingChainBuilder
{
    public static LoanProcessingHandler BuildStandardProcessingChain(IServiceProvider serviceProvider)
    {
        var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
        
        // 创建处理者
        var documentHandler = new DocumentationHandler(
            "DOC001", 
            "张文档", 
            loggerFactory.CreateLogger<DocumentationHandler>());
            
        var creditHandler = new CreditCheckHandler(
            "CRD001", 
            "李信审", 
            loggerFactory.CreateLogger<CreditCheckHandler>());
            
        var incomeHandler = new IncomeVerificationHandler(
            "INC001", 
            "王收入", 
            loggerFactory.CreateLogger<IncomeVerificationHandler>());
            
        var underwriterHandler = new UnderwriterHandler(
            "UND001", 
            "赵审核", 
            loggerFactory.CreateLogger<UnderwriterHandler>());
            
        var loanOfficerHandler = new FinalApprovalHandler(
            "OFF001", 
            "钱经理", 
            "贷款主管",
            loggerFactory.CreateLogger<FinalApprovalHandler>(),
            300000); // 30万审批权限
            
        var seniorManagerHandler = new SeniorApprovalHandler(
            "SEN001", 
            "孙总监", 
            loggerFactory.CreateLogger<SeniorApprovalHandler>(),
            1000000, // 100万审批权限
            500000); // 50万需额外风险评估
            
        var committeeHandler = new LoanCommitteeHandler(
            "COM001", 
            "贷款审批委员会", 
            loggerFactory.CreateLogger<LoanCommitteeHandler>());
        
        // 构建责任链
        documentHandler.SetNext(creditHandler)
                      .SetNext(incomeHandler)
                      .SetNext(underwriterHandler)
                      .SetNext(loanOfficerHandler)
                      .SetNext(seniorManagerHandler)
                      .SetNext(committeeHandler);
        
        return documentHandler; // 返回链的起点
    }
}

// 14. 贷款处理系统
public class LoanProcessingSystem
{
    private readonly LoanProcessingHandler _processingChain;
    private readonly ILogger<LoanProcessingSystem> _logger;
    
    public LoanProcessingSystem(LoanProcessingHandler processingChain, ILogger<LoanProcessingSystem> logger)
    {
        _processingChain = processingChain;
        _logger = logger;
    }
    
    public async Task<ProcessingResult> ProcessLoanApplicationAsync(LoanApplication application)
    {
        _logger.LogInformation("开始处理贷款申请: {ApplicationId}", application.ApplicationId);
        
        try
        {
            // 发送申请到责任链
            var result = await _processingChain.ProcessRequest(application);
            
            // 记录结果
            if (result.IsProcessed)
            {
                _logger.LogInformation("申请 {ApplicationId} 处理结果: {Status} - {Comments} (由 {Processor} 处理)",
                    application.ApplicationId, result.Status, result.Comments, result.ProcessorName);
            }
            else
            {
                _logger.LogWarning("申请 {ApplicationId} 未被处理", application.ApplicationId);
            }
            
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "处理申请 {ApplicationId} 时出错", application.ApplicationId);
            throw;
        }
    }
    
    public void PrintApplicationSummary(LoanApplication application)
    {
        _logger.LogInformation("=== 贷款申请 {ApplicationId} 摘要 ===", application.ApplicationId);
        _logger.LogInformation("客户: {CustomerName} ({CustomerId})", application.CustomerName, application.CustomerId);
        _logger.LogInformation("金额: ${Amount:N0}, 期限: {Term}个月, 目的: {Purpose}", 
            application.RequestedAmount, application.RequestedTermMonths, application.Purpose);
        _logger.LogInformation("当前状态: {Status}", application.Status);
        _logger.LogInformation("提交日期: {Date:yyyy-MM-dd HH:mm:ss}", application.ApplicationDate);
        
        if (application.Status == LoanApplicationStatus.Approved)
        {
            decimal monthlyPayment = application.CalculateEstimatedMonthlyPayment();
            _logger.LogInformation("估计月供: ${Payment:N2}", monthlyPayment);
        }
    }
    
    public void PrintProcessingHistory(LoanApplication application)
    {
        _logger.LogInformation("=== 贷款申请 {ApplicationId} 处理历史 ===", application.ApplicationId);
        
        if (application.ProcessingHistory.Count == 0)
        {
            _logger.LogInformation("无处理记录");
            return;
        }
        
        foreach (var record in application.ProcessingHistory)
        {
            _logger.LogInformation("{Date}: {Processor} ({Role}) - {OldStatus} -> {NewStatus} - {Comments}",
                record.ProcessingDate.ToString("yyyy-MM-dd HH:mm:ss"),
                record.ProcessorName,
                record.Role,
                record.PreviousStatus,
                record.NewStatus,
                record.Comments);
        }
    }
}

// 15. 客户端代码
public class Program
{
    public static async Task Main()
    {
        // 设置依赖注入
        var services = new ServiceCollection();
        
        // 添加日志
        services.AddLogging(builder =>
        {
            builder.AddConsole();
            builder.SetMinimumLevel(LogLevel.Information);
        });
        
        var serviceProvider = services.BuildServiceProvider();
        
        // 构建贷款处理责任链
        var processingChain = LoanProcessingChainBuilder.BuildStandardProcessingChain(serviceProvider);
        
        // 创建贷款处理系统
        var processingSystem = new LoanProcessingSystem(
            processingChain,
            serviceProvider.GetRequiredService<ILogger<LoanProcessingSystem>>()
        );
        
        // 创建几个样例贷款申请
        var loanApplications = CreateSampleApplications();
        
        // 处理每个申请
        foreach (var application in loanApplications)
        {
            Console.WriteLine("\n========================================");
            processingSystem.PrintApplicationSummary(application);
            
            var result = await processingSystem.ProcessLoanApplicationAsync(application);
            
            // 打印处理历史
            processingSystem.PrintProcessingHistory(application);
            
            Console.WriteLine("========================================\n");
        }
    }
    
    private static List<LoanApplication> CreateSampleApplications()
    {
        var applications = new List<LoanApplication>();
        
        // 1. 小额个人贷款 - 应该通过
        var application1 = new LoanApplication(
            "C00001",
            "张三",
            50000m, // 5万元
            36, // 3年期
            LoanPurpose.PersonalLoan
        );
        application1.CreditScore = 720;
        application1.AnnualIncome = 180000m; // 18万年收入
        application1.ExistingDebts = 100000m; // 10万现有债务
        
        // 添加文档
        application1.AddSupportingDocument("/documents/identity.pdf");
        application1.AddSupportingDocument("/documents/income.pdf");
        application1.AddSupportingDocument("/documents/bank.pdf");
        application1.AddSupportingDocument("/documents/loan_application.pdf");
        
        applications.Add(application1);
        
        // 2. 房屋装修贷款 - 缺少文档,应该被要求补充
        var application2 = new LoanApplication(
            "C00002",
            "李四",
            300000m, // 30万元
            60, // 5年期
            LoanPurpose.HomeImprovement
        );
        application2.CreditScore = 680;
        application2.AnnualIncome = 240000m; // 24万年收入
        application2.ExistingDebts = 500000m; // 50万现有债务(可能是房贷)
        
        // 只添加部分文档,缺少银行账单
        application2.AddSupportingDocument("/documents/identity.pdf");
        application2.AddSupportingDocument("/documents/income.pdf");
        application2.AddSupportingDocument("/documents/loan_application.pdf");
        
        applications.Add(application2);
        
        // 3. 大额商业贷款 - 信用分数低,应该被拒绝
        var application3 = new LoanApplication(
            "C00003",
            "王五",
            2000000m, // 200万元
            120, // 10年期
            LoanPurpose.BusinessLoan
        );
        application3.CreditScore = 580; // 信用分数较低
        application3.AnnualIncome = 500000m; // 50万年收入
        application3.ExistingDebts = 300000m; // 30万现有债务
        
        // 添加完整文档
        application3.AddSupportingDocument("/documents/identity.pdf");
        application3.AddSupportingDocument("/documents/income.pdf");
        application3.AddSupportingDocument("/documents/bank.pdf");
        application3.AddSupportingDocument("/documents/loan_application.pdf");
        application3.AddSupportingDocument("/documents/business_plan.pdf");
        application3.AddSupportingDocument("/documents/property.pdf");
        
        applications.Add(application3);
        
        // 4. 中等汽车贷款 - 债务收入比过高,应该被拒绝
        var application4 = new LoanApplication(
            "C00004",
            "赵六",
            200000m, // 20万元
            48, // 4年期
            LoanPurpose.AutoLoan
        );
        application4.CreditScore = 700;
        application4.AnnualIncome = 120000m; // 12万年收入
        application4.ExistingDebts = 600000m; // 60万现有债务
        
        // 添加完整文档
        application4.AddSupportingDocument("/documents/identity.pdf");
        application4.AddSupportingDocument("/documents/income.pdf");
        application4.AddSupportingDocument("/documents/bank.pdf");
        application4.AddSupportingDocument("/documents/loan_application.pdf");
        application4.AddSupportingDocument("/documents/vehicle.pdf");
        
        applications.Add(application4);
        
        // 5. 大额房屋贷款 - 需要高级审批
        var application5 = new LoanApplication(
            "C00005",
            "钱七",
            800000m, // 80万元
            240, // 20年期
            LoanPurpose.HomeRefinance
        );
        application5.CreditScore = 780; // 良好的信用分数
        application5.AnnualIncome = 400000m; // 40万年收入
        application5.ExistingDebts = 200000m; // 20万现有债务
        
        // 添加完整文档
        application5.AddSupportingDocument("/documents/identity.pdf");
        application5.AddSupportingDocument("/documents/income.pdf");
        application5.AddSupportingDocument("/documents/bank.pdf");
        application5.AddSupportingDocument("/documents/loan_application.pdf");
        application5.AddSupportingDocument("/documents/property.pdf");
        application5.AddSupportingDocument("/documents/appraisal.pdf");
        
        applications.Add(application5);
        
        return applications;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284

# 14. 命令模式

原理:
命令模式将请求封装为对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

思路:

  1. 创建一个命令接口,声明执行命令的方法
  2. 创建具体命令类,实现命令接口
  3. 命令类通常包含接收者对象和执行该命令所需的参数
  4. 创建调用者,用于存储并执行命令
  5. 客户端创建命令对象,设置接收者,然后将命令对象传递给调用者

前辈经验:

  • 当需要参数化对象的操作、队列操作或支持撤销操作时,使用命令模式
  • 命令模式将发出请求的对象与处理请求的对象解耦
  • 命令可以被保存在历史记录中,实现操作的撤销和重做
  • 命令模式允许创建由简单命令组成的复杂命令(宏命令)
  • 在实现事务、任务队列或命令日志记录时特别有用

业务场景:
文本编辑器应用,需要支持各种文本操作(如插入、删除、替换)并提供撤销和重做功能。

简单实现:

// 命令接口
public interface ICommand
{
    void Execute();
    void Undo();
}

// 文本编辑器(接收者)
public class TextEditor
{
    private string _text = "";
    
    public string GetText()
    {
        return _text;
    }
    
    public void InsertText(int position, string newText)
    {
        if (position < 0 || position > _text.Length)
        {
            throw new ArgumentOutOfRangeException("位置超出文本范围");
        }
        
        _text = _text.Insert(position, newText);
        Console.WriteLine($"在位置 {position} 插入文本: '{newText}'");
    }
    
    public void DeleteText(int position, int length)
    {
        if (position < 0 || position + length > _text.Length)
        {
            throw new ArgumentOutOfRangeException("位置或长度超出文本范围");
        }
        
        string deletedText = _text.Substring(position, length);
        _text = _text.Remove(position, length);
        Console.WriteLine($"删除位置 {position} 的文本: '{deletedText}'");
    }
    
    public void ReplaceText(int position, int length, string newText)
    {
        if (position < 0 || position + length > _text.Length)
        {
            throw new ArgumentOutOfRangeException("位置或长度超出文本范围");
        }
        
        string replacedText = _text.Substring(position, length);
        _text = _text.Remove(position, length).Insert(position, newText);
        Console.WriteLine($"替换位置 {position} 的文本: '{replacedText}' -> '{newText}'");
    }
}

// 具体命令 - 插入文本
public class InsertTextCommand : ICommand
{
    private readonly TextEditor _editor;
    private readonly int _position;
    private readonly string _textToInsert;
    
    public InsertTextCommand(TextEditor editor, int position, string textToInsert)
    {
        _editor = editor;
        _position = position;
        _textToInsert = textToInsert;
    }
    
    public void Execute()
    {
        _editor.InsertText(_position, _textToInsert);
    }
    
    public void Undo()
    {
        _editor.DeleteText(_position, _textToInsert.Length);
    }
}

// 具体命令 - 删除文本
public class DeleteTextCommand : ICommand
{
    private readonly TextEditor _editor;
    private readonly int _position;
    private readonly int _length;
    private string _deletedText;
    
    public DeleteTextCommand(TextEditor editor, int position, int length)
    {
        _editor = editor;
        _position = position;
        _length = length;
    }
    
    public void Execute()
    {
        // 在删除前保存文本,以便撤销时恢复
        _deletedText = _editor.GetText().Substring(_position, _length);
        _editor.DeleteText(_position, _length);
    }
    
    public void Undo()
    {
        _editor.InsertText(_position, _deletedText);
    }
}

// 具体命令 - 替换文本
public class ReplaceTextCommand : ICommand
{
    private readonly TextEditor _editor;
    private readonly int _position;
    private readonly int _length;
    private readonly string _newText;
    private string _replacedText;
    
    public ReplaceTextCommand(TextEditor editor, int position, int length, string newText)
    {
        _editor = editor;
        _position = position;
        _length = length;
        _newText = newText;
    }
    
    public void Execute()
    {
        // 在替换前保存原始文本,以便撤销时恢复
        _replacedText = _editor.GetText().Substring(_position, _length);
        _editor.ReplaceText(_position, _length, _newText);
    }
    
    public void Undo()
    {
        _editor.ReplaceText(_position, _newText.Length, _replacedText);
    }
}

// 命令历史记录(调用者)
public class CommandHistory
{
    private readonly Stack<ICommand> _undoStack = new Stack<ICommand>();
    private readonly Stack<ICommand> _redoStack = new Stack<ICommand>();
    
    public void ExecuteCommand(ICommand command)
    {
        command.Execute();
        _undoStack.Push(command);
        _redoStack.Clear(); // 执行新命令后清除重做栈
    }
    
    public void Undo()
    {
        if (_undoStack.Count > 0)
        {
            ICommand command = _undoStack.Pop();
            command.Undo();
            _redoStack.Push(command);
        }
        else
        {
            Console.WriteLine("没有可撤销的操作");
        }
    }
    
    public void Redo()
    {
        if (_redoStack.Count > 0)
        {
            ICommand command = _redoStack.Pop();
            command.Execute();
            _undoStack.Push(command);
        }
        else
        {
            Console.WriteLine("没有可重做的操作");
        }
    }
}

// 客户端代码
public class Client
{
    public static void Main()
    {
        // 创建接收者
        TextEditor editor = new TextEditor();
        
        // 创建命令历史记录
        CommandHistory history = new CommandHistory();
        
        // 创建并执行命令
        ICommand insertCommand = new InsertTextCommand(editor, 0, "Hello, ");
        history.ExecuteCommand(insertCommand);
        Console.WriteLine($"当前文本: {editor.GetText()}");
        
        ICommand insertCommand2 = new InsertTextCommand(editor, 7, "World!");
        history.ExecuteCommand(insertCommand2);
        Console.WriteLine($"当前文本: {editor.GetText()}");
        
        ICommand replaceCommand = new ReplaceTextCommand(editor, 0, 5, "Hi,");
        history.ExecuteCommand(replaceCommand);
        Console.WriteLine($"当前文本: {editor.GetText()}");
        
        // 撤销操作
        Console.WriteLine("\n撤销上一次操作:");
        history.Undo();
        Console.WriteLine($"当前文本: {editor.GetText()}");
        
        // 重做操作
        Console.WriteLine("\n重做上一次操作:");
        history.Redo();
        Console.WriteLine($"当前文本: {editor.GetText()}");
        
        // 删除操作
        ICommand deleteCommand = new DeleteTextCommand(editor, 3, 4);
        history.ExecuteCommand(deleteCommand);
        Console.WriteLine($"当前文本: {editor.GetText()}");
        
        // 撤销两次操作
        Console.WriteLine("\n连续撤销两次操作:");
        history.Undo();
        Console.WriteLine($"当前文本: {editor.GetText()}");
        
        history.Undo();
        Console.WriteLine($"当前文本: {editor.GetText()}");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

复杂实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// 1. 命令接口
public interface ICommand
{
    Task<bool> ExecuteAsync();
    Task<bool> UndoAsync();
    string GetName();
    string GetDescription();
    bool CanExecute();
    bool IsUndoable();
}

// 2. 撤销栈接口
public interface IUndoRedoManager
{
    void PushCommand(ICommand command);
    ICommand PopUndoCommand();
    ICommand PopRedoCommand();
    bool CanUndo();
    bool CanRedo();
    List<ICommand> GetUndoHistory();
    List<ICommand> GetRedoHistory();
    void Clear();
}

// 3. 撤销栈实现
public class UndoRedoManager : IUndoRedoManager
{
    private readonly Stack<ICommand> _undoStack = new Stack<ICommand>();
    private readonly Stack<ICommand> _redoStack = new Stack<ICommand>();
    private readonly int _maxHistorySize;
    
    public UndoRedoManager(int maxHistorySize = 100)
    {
        _maxHistorySize = maxHistorySize;
    }
    
    public void PushCommand(ICommand command)
    {
        _undoStack.Push(command);
        _redoStack.Clear(); // 执行新命令后清除重做栈
        
        // 限制撤销栈大小
        while (_undoStack.Count > _maxHistorySize)
        {
            _undoStack.Pop();
        }
    }
    
    public ICommand PopUndoCommand()
    {
        if (_undoStack.Count == 0)
            return null;
            
        return _undoStack.Pop();
    }
    
    public ICommand PopRedoCommand()
    {
        if (_redoStack.Count == 0)
            return null;
            
        return _redoStack.Pop();
    }
    
    public bool CanUndo()
    {
        return _undoStack.Count > 0;
    }
    
    public bool CanRedo()
    {
        return _redoStack.Count > 0;
    }
    
    public List<ICommand> GetUndoHistory()
    {
        return _undoStack.ToList();
    }
    
    public List<ICommand> GetRedoHistory()
    {
        return _redoStack.ToList();
    }
    
    public void Clear()
    {
        _undoStack.Clear();
        _redoStack.Clear();
    }
}

// 4. 文档类 - 接收者
public class Document
{
    private StringBuilder _content;
    private string _name;
    private bool _isDirty;
    
    public event EventHandler<DocumentChangedEventArgs> DocumentChanged;
    
    public Document(string name = "Untitled", string initialContent = "")
    {
        _name = name;
        _content = new StringBuilder(initialContent);
        _isDirty = false;
    }
    
    public string GetName()
    {
        return _name;
    }
    
    public void SetName(string name)
    {
        if (_name != name)
        {
            string oldName = _name;
            _name = name;
            OnDocumentChanged(new DocumentChangedEventArgs
            {
                ChangeType = DocumentChangeType.NameChanged,
                OldName = oldName,
                NewName = name
            });
        }
    }
    
    public string GetContent()
    {
        return _content.ToString();
    }
    
    public void SetContent(string content)
    {
        string oldContent = _content.ToString();
        _content.Clear();
        _content.Append(content);
        
        _isDirty = true;
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = DocumentChangeType.ContentReplaced,
            OldContent = oldContent,
            NewContent = content
        });
    }
    
    public void InsertText(int position, string text)
    {
        ValidatePosition(position);
        
        _content.Insert(position, text);
        _isDirty = true;
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = DocumentChangeType.TextInserted,
            Position = position,
            Text = text
        });
    }
    
    public void DeleteText(int position, int length)
    {
        ValidateRange(position, length);
        
        string deletedText = _content.ToString(position, length);
        _content.Remove(position, length);
        _isDirty = true;
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = DocumentChangeType.TextDeleted,
            Position = position,
            Text = deletedText,
            Length = length
        });
    }
    
    public void ReplaceText(int position, int length, string newText)
    {
        ValidateRange(position, length);
        
        string replacedText = _content.ToString(position, length);
        _content.Remove(position, length);
        _content.Insert(position, newText);
        _isDirty = true;
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = DocumentChangeType.TextReplaced,
            Position = position,
            Text = replacedText,
            NewText = newText,
            Length = length
        });
    }
    
    public bool IsDirty()
    {
        return _isDirty;
    }
    
    public void MarkAsSaved()
    {
        _isDirty = false;
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = DocumentChangeType.Saved
        });
    }
    
    public int GetLength()
    {
        return _content.Length;
    }
    
    private void ValidatePosition(int position)
    {
        if (position < 0 || position > _content.Length)
        {
            throw new ArgumentOutOfRangeException(nameof(position), "位置超出文档范围");
        }
    }
    
    private void ValidateRange(int position, int length)
    {
        ValidatePosition(position);
        
        if (length < 0 || position + length > _content.Length)
        {
            throw new ArgumentOutOfRangeException(nameof(length), "长度超出文档范围");
        }
    }
    
    protected virtual void OnDocumentChanged(DocumentChangedEventArgs e)
    {
        DocumentChanged?.Invoke(this, e);
    }
}

// 5. 文档变更事件参数
public class DocumentChangedEventArgs : EventArgs
{
    public DocumentChangeType ChangeType { get; set; }
    public int Position { get; set; }
    public string Text { get; set; }
    public string NewText { get; set; }
    public int Length { get; set; }
    public string OldName { get; set; }
    public string NewName { get; set; }
    public string OldContent { get; set; }
    public string NewContent { get; set; }
}

// 6. 文档变更类型枚举
public enum DocumentChangeType
{
    TextInserted,
    TextDeleted,
    TextReplaced,
    NameChanged,
    ContentReplaced,
    Saved
}

// 7. 命令抽象基类
public abstract class DocumentCommand : ICommand
{
    protected Document _document;
    
    public DocumentCommand(Document document)
    {
        _document = document;
    }
    
    public abstract Task<bool> ExecuteAsync();
    public abstract Task<bool> UndoAsync();
    public abstract string GetName();
    public abstract string GetDescription();
    
    public virtual bool CanExecute()
    {
        return true;
    }
    
    public virtual bool IsUndoable()
    {
        return true;
    }
}

// 8. 具体命令 - 插入文本
public class InsertTextCommand : DocumentCommand
{
    private readonly int _position;
    private readonly string _text;
    
    public InsertTextCommand(Document document, int position, string text)
        : base(document)
    {
        _position = position;
        _text = text;
    }
    
    public override async Task<bool> ExecuteAsync()
    {
        try
        {
            _document.InsertText(_position, _text);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"插入文本失败: {ex.Message}");
            return false;
        }
    }
    
    public override async Task<bool> UndoAsync()
    {
        try
        {
            _document.DeleteText(_position, _text.Length);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"撤销插入文本失败: {ex.Message}");
            return false;
        }
    }
    
    public override string GetName()
    {
        return "插入文本";
    }
    
    public override string GetDescription()
    {
        if (_text.Length > 10)
        {
            return $"在位置 {_position} 插入文本: '{_text.Substring(0, 10)}...'";
        }
        
        return $"在位置 {_position} 插入文本: '{_text}'";
    }
    
    public override bool CanExecute()
    {
        return _position >= 0 && _position <= _document.GetLength();
    }
}

// 9. 具体命令 - 删除文本
public class DeleteTextCommand : DocumentCommand
{
    private readonly int _position;
    private readonly int _length;
    private string _deletedText;
    
    public DeleteTextCommand(Document document, int position, int length)
        : base(document)
    {
        _position = position;
        _length = length;
    }
    
    public override async Task<bool> ExecuteAsync()
    {
        try
        {
            // 保存要删除的文本,以便撤销时恢复
            _deletedText = _document.GetContent().Substring(_position, _length);
            _document.DeleteText(_position, _length);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"删除文本失败: {ex.Message}");
            return false;
        }
    }
    
    public override async Task<bool> UndoAsync()
    {
        try
        {
            _document.InsertText(_position, _deletedText);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"撤销删除文本失败: {ex.Message}");
            return false;
        }
    }
    
    public override string GetName()
    {
        return "删除文本";
    }
    
    public override string GetDescription()
    {
        if (_deletedText != null && _deletedText.Length > 10)
        {
            return $"删除位置 {_position} 的文本: '{_deletedText.Substring(0, 10)}...'";
        }
        
        string text = _deletedText ?? $"{_length} 个字符";
        return $"删除位置 {_position} 的文本: '{text}'";
    }
    
    public override bool CanExecute()
    {
        return _position >= 0 && _length > 0 && _position + _length <= _document.GetLength();
    }
}

// 10. 具体命令 - 替换文本
public class ReplaceTextCommand : DocumentCommand
{
    private readonly int _position;
    private readonly int _length;
    private readonly string _newText;
    private string _replacedText;
    
    public ReplaceTextCommand(Document document, int position, int length, string newText)
        : base(document)
    {
        _position = position;
        _length = length;
        _newText = newText;
    }
    
    public override async Task<bool> ExecuteAsync()
    {
        try
        {
            // 保存要替换的文本,以便撤销时恢复
            _replacedText = _document.GetContent().Substring(_position, _length);
            _document.ReplaceText(_position, _length, _newText);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"替换文本失败: {ex.Message}");
            return false;
        }
    }
    
    public override async Task<bool> UndoAsync()
    {
        try
        {
            _document.ReplaceText(_position, _newText.Length, _replacedText);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"撤销替换文本失败: {ex.Message}");
            return false;
        }
    }
    
    public override string GetName()
    {
        return "替换文本";
    }
    
    public override string GetDescription()
    {
        string oldText = _replacedText ?? $"{_length} 个字符";
        string newText = _newText;
        
        if (oldText.Length > 10)
            oldText = oldText.Substring(0, 10) + "...";
            
        if (newText.Length > 10)
            newText = newText.Substring(0, 10) + "...";
            
        return $"将位置 {_position} 的文本 '{oldText}' 替换为 '{newText}'";
    }
    
    public override bool CanExecute()
    {
        return _position >= 0 && _length > 0 && _position + _length <= _document.GetLength();
    }
}

// 11. 具体命令 - 重命名文档
public class RenameDocumentCommand : DocumentCommand
{
    private readonly string _newName;
    private string _oldName;
    
    public RenameDocumentCommand(Document document, string newName)
        : base(document)
    {
        _newName = newName;
    }
    
    public override async Task<bool> ExecuteAsync()
    {
        try
        {
            _oldName = _document.GetName();
            _document.SetName(_newName);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"重命名文档失败: {ex.Message}");
            return false;
        }
    }
    
    public override async Task<bool> UndoAsync()
    {
        try
        {
            _document.SetName(_oldName);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"撤销重命名文档失败: {ex.Message}");
            return false;
        }
    }
    
    public override string GetName()
    {
        return "重命名文档";
    }
    
    public override string GetDescription()
    {
        return $"将文档从 '{_oldName}' 重命名为 '{_newName}'";
    }
    
    public override bool CanExecute()
    {
        return !string.IsNullOrEmpty(_newName);
    }
}

// 12. 具体命令 - 清空文档
public class ClearDocumentCommand : DocumentCommand
{
    private string _originalContent;
    
    public ClearDocumentCommand(Document document)
        : base(document)
    {
    }
    
    public override async Task<bool> ExecuteAsync()
    {
        try
        {
            _originalContent = _document.GetContent();
            _document.SetContent("");
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"清空文档失败: {ex.Message}");
            return false;
        }
    }
    
    public override async Task<bool> UndoAsync()
    {
        try
        {
            _document.SetContent(_originalContent);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"撤销清空文档失败: {ex.Message}");
            return false;
        }
    }
    
    public override string GetName()
    {
        return "清空文档";
    }
    
    public override string GetDescription()
    {
        return "清空文档内容";
    }
    
    public override bool CanExecute()
    {
        return _document.GetLength() > 0;
    }
}

// 13. 宏命令 - 组合多个命令
public class MacroCommand : ICommand
{
    private readonly List<ICommand> _commands = new List<ICommand>();
    private readonly string _name;
    private readonly string _description;
    
    public MacroCommand(string name, string description)
    {
        _name = name;
        _description = description;
    }
    
    public void AddCommand(ICommand command)
    {
        _commands.Add(command);
    }
    
    public async Task<bool> ExecuteAsync()
    {
        foreach (var command in _commands)
        {
            if (!command.CanExecute())
            {
                Console.WriteLine($"无法执行命令: {command.GetName()}");
                return false;
            }
            
            bool success = await command.ExecuteAsync();
            if (!success)
            {
                // 如果任何一个命令执行失败,尝试回滚已执行的命令
                await RollbackAsync(_commands.IndexOf(command));
                return false;
            }
        }
        
        return true;
    }
    
    public async Task<bool> UndoAsync()
    {
        // 以相反的顺序撤销命令
        for (int i = _commands.Count - 1; i >= 0; i--)
        {
            ICommand command = _commands[i];
            if (command.IsUndoable())
            {
                bool success = await command.UndoAsync();
                if (!success)
                {
                    Console.WriteLine($"撤销宏命令失败,命令: {command.GetName()}");
                    return false;
                }
            }
        }
        
        return true;
    }
    
    private async Task RollbackAsync(int failedCommandIndex)
    {
        // 回滚已执行的命令
        for (int i = failedCommandIndex - 1; i >= 0; i--)
        {
            ICommand command = _commands[i];
            if (command.IsUndoable())
            {
                await command.UndoAsync();
            }
        }
    }
    
    public string GetName()
    {
        return _name;
    }
    
    public string GetDescription()
    {
        return _description;
    }
    
    public bool CanExecute()
    {
        return _commands.All(cmd => cmd.CanExecute());
    }
    
    public bool IsUndoable()
    {
        return _commands.Any(cmd => cmd.IsUndoable());
    }
    
    public List<ICommand> GetCommands()
    {
        return new List<ICommand>(_commands);
    }
}

// 14. 不可撤销命令 - 保存文档
public class SaveDocumentCommand : DocumentCommand
{
    private readonly string _filePath;
    
    public SaveDocumentCommand(Document document, string filePath)
        : base(document)
    {
        _filePath = filePath;
    }
    
    public override async Task<bool> ExecuteAsync()
    {
        try
        {
            Console.WriteLine($"保存文档到 {_filePath}");
            
            // 实际应用中,这里应该将文档内容写入文件
            // await File.WriteAllTextAsync(_filePath, _document.GetContent());
            
            // 模拟文件写入
            await Task.Delay(100);
            
            // 标记文档为已保存状态
            _document.MarkAsSaved();
            
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"保存文档失败: {ex.Message}");
            return false;
        }
    }
    
    public override async Task<bool> UndoAsync()
    {
        // 保存操作不能撤销
        Console.WriteLine("保存操作不能撤销");
        return false;
    }
    
    public override string GetName()
    {
        return "保存文档";
    }
    
    public override string GetDescription()
    {
        return $"将文档保存到 {_filePath}";
    }
    
    public override bool IsUndoable()
    {
        return false;
    }
}

// 15. 文档编辑器 - 调用者
public class TextEditor
{
    private readonly Document _document;
    private readonly IUndoRedoManager _undoRedoManager;
    
    public TextEditor(string documentName = "Untitled", string initialContent = "")
    {
        _document = new Document(documentName, initialContent);
        _undoRedoManager = new UndoRedoManager();
        
        _document.DocumentChanged += Document_Changed;
    }
    
    private void Document_Changed(object sender, DocumentChangedEventArgs e)
    {
        Console.WriteLine($"文档变更: {e.ChangeType}");
    }
    
    public async Task ExecuteCommandAsync(ICommand command)
    {
        if (!command.CanExecute())
        {
            Console.WriteLine($"无法执行命令: {command.GetName()}");
            return;
        }
        
        bool success = await command.ExecuteAsync();
        
        if (success && command.IsUndoable())
        {
            _undoRedoManager.PushCommand(command);
            Console.WriteLine($"执行命令: {command.GetDescription()}");
        }
    }
    
    public async Task UndoAsync()
    {
        if (!_undoRedoManager.CanUndo())
        {
            Console.WriteLine("没有可撤销的操作");
            return;
        }
        
        ICommand command = _undoRedoManager.PopUndoCommand();
        bool success = await command.UndoAsync();
        
        if (success)
        {
            Console.WriteLine($"撤销命令: {command.GetDescription()}");
            _undoRedoManager.GetRedoHistory().Insert(0, command);
        }
        else
        {
            Console.WriteLine($"撤销命令失败: {command.GetDescription()}");
        }
    }
    
    public async Task RedoAsync()
    {
        if (!_undoRedoManager.CanRedo())
        {
            Console.WriteLine("没有可重做的操作");
            return;
        }
        
        ICommand command = _undoRedoManager.PopRedoCommand();
        bool success = await command.ExecuteAsync();
        
        if (success)
        {
            Console.WriteLine($"重做命令: {command.GetDescription()}");
            _undoRedoManager.PushCommand(command);
        }
        else
        {
            Console.WriteLine($"重做命令失败: {command.GetDescription()}");
        }
    }
    
    public void PrintUndoHistory()
    {
        var undoHistory = _undoRedoManager.GetUndoHistory();
        
        Console.WriteLine("\n撤销历史记录:");
        if (undoHistory.Count == 0)
        {
            Console.WriteLine("  (空)");
            return;
        }
        
        for (int i = 0; i < Math.Min(undoHistory.Count, 5); i++)
        {
            Console.WriteLine($"  {i + 1}. {undoHistory[i].GetDescription()}");
        }
        
        if (undoHistory.Count > 5)
        {
            Console.WriteLine($"  ... 还有 {undoHistory.Count - 5} 个命令");
        }
    }
    
    public void PrintRedoHistory()
    {
        var redoHistory = _undoRedoManager.GetRedoHistory();
        
        Console.WriteLine("\n重做历史记录:");
        if (redoHistory.Count == 0)
        {
            Console.WriteLine("  (空)");
            return;
        }
        
        for (int i = 0; i < Math.Min(redoHistory.Count, 5); i++)
        {
            Console.WriteLine($"  {i + 1}. {redoHistory[i].GetDescription()}");
        }
        
        if (redoHistory.Count > 5)
        {
            Console.WriteLine($"  ... 还有 {redoHistory.Count - 5} 个命令");
        }
    }
    
    public void PrintDocumentContent()
    {
        Console.WriteLine($"\n文档 '{_document.GetName()}' 内容:");
        Console.WriteLine("----------");
        Console.WriteLine(_document.GetContent());
        Console.WriteLine("----------");
        
        if (_document.IsDirty())
        {
            Console.WriteLine("(未保存)");
        }
    }
    
    public Document GetDocument()
    {
        return _document;
    }
}

// 16. 客户端代码
public class Client
{
    public static async Task Main()
    {
        // 创建文本编辑器
        TextEditor editor = new TextEditor("MyDocument.txt");
        
        // 执行插入命令
        await editor.ExecuteCommandAsync(new InsertTextCommand(editor.GetDocument(), 0, "Hello, World!"));
        editor.PrintDocumentContent();
        
        // 执行删除命令
        await editor.ExecuteCommandAsync(new DeleteTextCommand(editor.GetDocument(), 5, 7));
        editor.PrintDocumentContent();
        
        // 执行替换命令
        await editor.ExecuteCommandAsync(new ReplaceTextCommand(editor.GetDocument(), 0, 5, "Hi"));
        editor.PrintDocumentContent();
        
        // 撤销操作
        Console.WriteLine("\n撤销上一次操作:");
        await editor.UndoAsync();
        editor.PrintDocumentContent();
        
        // 重做操作
        Console.WriteLine("\n重做上一次操作:");
        await editor.RedoAsync();
        editor.PrintDocumentContent();
        
        // 创建并执行宏命令
        Console.WriteLine("\n执行宏命令:");
        var macro = new MacroCommand("格式化段落", "删除末尾并添加新段落");
        macro.AddCommand(new DeleteTextCommand(editor.GetDocument(), 6, 1));
        macro.AddCommand(new InsertTextCommand(editor.GetDocument(), 6, "\n\nNew paragraph!"));
        
        await editor.ExecuteCommandAsync(macro);
        editor.PrintDocumentContent();
        
        // 执行重命名命令
        await editor.ExecuteCommandAsync(new RenameDocumentCommand(editor.GetDocument(), "MyEditedDocument.txt"));
        
        // 执行保存命令(不可撤销)
        await editor.ExecuteCommandAsync(new SaveDocumentCommand(editor.GetDocument(), "C:\\temp\\MyEditedDocument.txt"));
        
        // 显示撤销和重做历史
        editor.PrintUndoHistory();
        editor.PrintRedoHistory();
        
        // 多次撤销
        Console.WriteLine("\n连续撤销三次操作:");
        await editor.UndoAsync();
        await editor.UndoAsync();
        await editor.UndoAsync();
        editor.PrintDocumentContent();
        
        // 显示更新后的历史
        editor.PrintUndoHistory();
        editor.PrintRedoHistory();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972

业务场景结合:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;

// 股票交易系统 - 使用命令模式处理交易指令

// 1. 交易命令接口
public interface ITradeCommand
{
    Task<TradeResult> ExecuteAsync();
    Task<TradeResult> UndoAsync();
    string GetCommandId();
    string GetType();
    string GetDescription();
    bool IsUndoable();
    bool IsValid();
}

// 2. 交易结果类
public class TradeResult
{
    public bool Success { get; set; }
    public string Message { get; set; }
    public string TradeId { get; set; }
    public decimal ExecutedPrice { get; set; }
    public int ExecutedQuantity { get; set; }
    public DateTime ExecutionTime { get; set; }
    public Dictionary<string, object> AdditionalInfo { get; set; } = new Dictionary<string, object>();

    public static TradeResult Successful(string tradeId, decimal executedPrice, int executedQuantity, string message = "交易成功")
    {
        return new TradeResult
        {
            Success = true,
            TradeId = tradeId,
            ExecutedPrice = executedPrice,
            ExecutedQuantity = executedQuantity,
            ExecutionTime = DateTime.Now,
            Message = message
        };
    }

    public static TradeResult Failed(string message)
    {
        return new TradeResult
        {
            Success = false,
            Message = message,
            ExecutionTime = DateTime.Now
        };
    }
}

// 3. 交易类型枚举
public enum TradeType
{
    Buy,
    Sell,
    ShortSell,
    BuyToCover,
    Transfer
}

// 4. 订单类型枚举
public enum OrderType
{
    Market,
    Limit,
    Stop,
    StopLimit
}

// 5. 股票交易命令基类
public abstract class TradeCommand : ITradeCommand
{
    protected readonly string _commandId;
    protected readonly string _accountId;
    protected readonly string _symbol;
    protected readonly int _quantity;
    protected readonly TradeType _tradeType;
    protected readonly IStockMarket _market;
    protected readonly ILogger _logger;
    protected TradeResult _executionResult;

    protected TradeCommand(
        string accountId,
        string symbol,
        int quantity,
        TradeType tradeType,
        IStockMarket market,
        ILogger logger)
    {
        _commandId = Guid.NewGuid().ToString();
        _accountId = accountId;
        _symbol = symbol;
        _quantity = quantity;
        _tradeType = tradeType;
        _market = market;
        _logger = logger;
    }

    public abstract Task<TradeResult> ExecuteAsync();
    public abstract Task<TradeResult> UndoAsync();

    public string GetCommandId()
    {
        return _commandId;
    }

    public abstract string GetType();

    public string GetDescription()
    {
        return $"{_tradeType} {_quantity} shares of {_symbol}";
    }

    public virtual bool IsUndoable()
    {
        // 通常,只有成功执行的交易才能撤销
        return _executionResult != null && _executionResult.Success;
    }

    public virtual bool IsValid()
    {
        // 基本验证
        if (string.IsNullOrEmpty(_accountId))
        {
            _logger.LogWarning("无效的账户ID");
            return false;
        }

        if (string.IsNullOrEmpty(_symbol))
        {
            _logger.LogWarning("无效的股票代码");
            return false;
        }

        if (_quantity <= 0)
        {
            _logger.LogWarning("交易数量必须大于0");
            return false;
        }

        return true;
    }
}

// 6. 市价交易命令
public class MarketOrderCommand : TradeCommand
{
    private readonly OrderType _orderType = OrderType.Market;

    public MarketOrderCommand(
        string accountId,
        string symbol,
        int quantity,
        TradeType tradeType,
        IStockMarket market,
        ILogger logger)
        : base(accountId, symbol, quantity, tradeType, market, logger)
        {
        }

    public override async Task<TradeResult> ExecuteAsync()
    {
        if (!IsValid())
        {
            return TradeResult.Failed("交易验证失败");
        }

        _logger.LogInformation("执行市价单: {TradeType} {Quantity} 股 {Symbol}", 
                               _tradeType, _quantity, _symbol);

        try
        {
            // 执行市价交易
            var quoteInfo = await _market.GetQuoteAsync(_symbol);
            decimal price = _tradeType == TradeType.Buy || _tradeType == TradeType.BuyToCover
                ? quoteInfo.AskPrice
                : quoteInfo.BidPrice;

            var result = await _market.ExecuteTradeAsync(
                _accountId, 
                _symbol, 
                _quantity, 
                price, 
                _tradeType, 
                _orderType);

            _executionResult = result;

            if (result.Success)
            {
                _logger.LogInformation("市价单执行成功: {TradeId}, 价格: {Price}, 数量: {Quantity}", 
                                       result.TradeId, result.ExecutedPrice, result.ExecutedQuantity);
            }
            else
            {
                _logger.LogWarning("市价单执行失败: {Message}", result.Message);
            }

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "执行市价单时出错");
            return TradeResult.Failed($"执行市价单出错: {ex.Message}");
        }
    }

    public override async Task<TradeResult> UndoAsync()
    {
        if (!IsUndoable())
        {
            return TradeResult.Failed("交易无法撤销");
        }

        _logger.LogInformation("撤销市价单: {TradeId}, {TradeType} {Quantity} 股 {Symbol}", 
                               _executionResult.TradeId, _tradeType, _quantity, _symbol);

        try
        {
            // 执行反向交易
            TradeType reverseType = GetReverseTradeType(_tradeType);

            var quoteInfo = await _market.GetQuoteAsync(_symbol);
            decimal price = reverseType == TradeType.Buy || reverseType == TradeType.BuyToCover
                ? quoteInfo.AskPrice
                : quoteInfo.BidPrice;

            var result = await _market.ExecuteTradeAsync(
                _accountId, 
                _symbol, 
                _quantity, 
                price, 
                reverseType, 
                _orderType,
                isReversal: true,
                originalTradeId: _executionResult.TradeId);

            if (result.Success)
            {
                _logger.LogInformation("市价单撤销成功: {TradeId}", result.TradeId);
            }
            else
            {
                _logger.LogWarning("市价单撤销失败: {Message}", result.Message);
            }

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "撤销市价单时出错");
            return TradeResult.Failed($"撤销市价单出错: {ex.Message}");
        }
    }

    private TradeType GetReverseTradeType(TradeType type)
    {
        return type switch
        {
                TradeType.Buy => TradeType.Sell,
                TradeType.Sell => TradeType.Buy,
                TradeType.ShortSell => TradeType.BuyToCover,
                TradeType.BuyToCover => TradeType.ShortSell,
                _ => throw new ArgumentException($"不支持的交易类型: {type}")
        };
    }

    public override string GetType()
    {
        return "市价单";
    }

    public override bool IsValid()
    {
        if (!base.IsValid())
            return false;

        // 市价单没有其他特殊验证
        return true;
    }
}

// 7. 限价交易命令
public class LimitOrderCommand : TradeCommand
{
    private readonly OrderType _orderType = OrderType.Limit;
    private readonly decimal _limitPrice;

    public LimitOrderCommand(
        string accountId,
        string symbol,
        int quantity,
        decimal limitPrice,
        TradeType tradeType,
        IStockMarket market,
        ILogger logger)
        : base(accountId, symbol, quantity, tradeType, market, logger)
        {
            _limitPrice = limitPrice;
        }

    public override async Task<TradeResult> ExecuteAsync()
    {
        if (!IsValid())
        {
            return TradeResult.Failed("交易验证失败");
        }

        _logger.LogInformation("提交限价单: {TradeType} {Quantity} 股 {Symbol} 价格 {Price}", 
                               _tradeType, _quantity, _symbol, _limitPrice);

        try
        {
            // 执行限价交易
            var result = await _market.ExecuteTradeAsync(
                _accountId, 
                _symbol, 
                _quantity, 
                _limitPrice, 
                _tradeType, 
                _orderType);

            _executionResult = result;

            if (result.Success)
            {
                _logger.LogInformation("限价单提交成功: {TradeId}", result.TradeId);
            }
            else
            {
                _logger.LogWarning("限价单提交失败: {Message}", result.Message);
            }

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "提交限价单时出错");
            return TradeResult.Failed($"提交限价单出错: {ex.Message}");
        }
    }

    public override async Task<TradeResult> UndoAsync()
    {
        if (!IsUndoable())
        {
            return TradeResult.Failed("交易无法撤销");
        }

        _logger.LogInformation("撤销限价单: {TradeId}", _executionResult.TradeId);

        try
        {
            // 对于限价单,撤销通常是取消订单
            var result = await _market.CancelOrderAsync(_executionResult.TradeId);

            if (result.Success)
            {
                _logger.LogInformation("限价单撤销成功: {TradeId}", _executionResult.TradeId);
            }
            else
            {
                _logger.LogWarning("限价单撤销失败: {Message}", result.Message);
            }

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "撤销限价单时出错");
            return TradeResult.Failed($"撤销限价单出错: {ex.Message}");
        }
    }

    public override string GetType()
    {
        return "限价单";
    }

    public override string GetDescription()
    {
        return $"{base.GetDescription()} at limit price {_limitPrice:C}";
    }

    public override bool IsValid()
    {
        if (!base.IsValid())
            return false;

        // 限价单特殊验证
        if (_limitPrice <= 0)
        {
            _logger.LogWarning("限价必须大于0");
            return false;
        }

        // 买单限价需要大于0,卖单同理
        return true;
    }
}

// 8. 止损单命令
public class StopOrderCommand : TradeCommand
{
    private readonly OrderType _orderType = OrderType.Stop;
    private readonly decimal _stopPrice;

    public StopOrderCommand(
        string accountId,
        string symbol,
        int quantity,
        decimal stopPrice,
        TradeType tradeType,
        IStockMarket market,
        ILogger logger)
        : base(accountId, symbol, quantity, tradeType, market, logger)
        {
            _stopPrice = stopPrice;
        }

    public override async Task<TradeResult> ExecuteAsync()
    {
        if (!IsValid())
        {
            return TradeResult.Failed("交易验证失败");
        }

        _logger.LogInformation("提交止损单: {TradeType} {Quantity} 股 {Symbol} 触发价格 {Price}", 
                               _tradeType, _quantity, _symbol, _stopPrice);

        try
        {
            // 执行止损交易
            var result = await _market.ExecuteTradeAsync(
                _accountId, 
                _symbol, 
                _quantity, 
                _stopPrice, 
                _tradeType, 
                _orderType);

            _executionResult = result;

            if (result.Success)
            {
                _logger.LogInformation("止损单提交成功: {TradeId}", result.TradeId);
            }
            else
            {
                _logger.LogWarning("止损单提交失败: {Message}", result.Message);
            }

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "提交止损单时出错");
            return TradeResult.Failed($"提交止损单出错: {ex.Message}");
        }
    }

    public override async Task<TradeResult> UndoAsync()
    {
        if (!IsUndoable())
        {
            return TradeResult.Failed("交易无法撤销");
        }

        _logger.LogInformation("撤销止损单: {TradeId}", _executionResult.TradeId);

        try
        {
            // 对于止损单,撤销通常是取消订单
            var result = await _market.CancelOrderAsync(_executionResult.TradeId);

            if (result.Success)
            {
                _logger.LogInformation("止损单撤销成功: {TradeId}", _executionResult.TradeId);
            }
            else
            {
                _logger.LogWarning("止损单撤销失败: {Message}", result.Message);
            }

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "撤销止损单时出错");
            return TradeResult.Failed($"撤销止损单出错: {ex.Message}");
        }
    }

    public override string GetType()
    {
        return "止损单";
    }

    public override string GetDescription()
    {
        return $"{base.GetDescription()} at stop price {_stopPrice:C}";
    }

    public override bool IsValid()
    {
        if (!base.IsValid())
            return false;

        // 止损单特殊验证
        if (_stopPrice <= 0)
        {
            _logger.LogWarning("止损价必须大于0");
            return false;
        }

        return true;
    }
}

// 9. 股票转移命令
public class TransferStockCommand : TradeCommand
{
    private readonly string _toAccountId;

    public TransferStockCommand(
        string fromAccountId,
        string toAccountId,
        string symbol,
        int quantity,
        IStockMarket market,
        ILogger logger)
        : base(fromAccountId, symbol, quantity, TradeType.Transfer, market, logger)
        {
            _toAccountId = toAccountId;
        }

    public override async Task<TradeResult> ExecuteAsync()
    {
        if (!IsValid())
        {
            return TradeResult.Failed("交易验证失败");
        }

        _logger.LogInformation("执行股票转移: {Quantity} 股 {Symbol} 从账户 {FromAccount} 到 {ToAccount}", 
                               _quantity, _symbol, _accountId, _toAccountId);

        try
        {
            // 执行股票转移
            var result = await _market.TransferStockAsync(_accountId, _toAccountId, _symbol, _quantity);

            _executionResult = result;

            if (result.Success)
            {
                _logger.LogInformation("股票转移成功: {TradeId}", result.TradeId);
            }
            else
            {
                _logger.LogWarning("股票转移失败: {Message}", result.Message);
            }

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "执行股票转移时出错");
            return TradeResult.Failed($"执行股票转移出错: {ex.Message}");
        }
    }

    public override async Task<TradeResult> UndoAsync()
    {
        if (!IsUndoable())
        {
            return TradeResult.Failed("交易无法撤销");
        }

        _logger.LogInformation("撤销股票转移: {TradeId}, {Quantity} 股 {Symbol} 从账户 {ToAccount} 到 {FromAccount}", 
                               _executionResult.TradeId, _quantity, _symbol, _toAccountId, _accountId);

        try
        {
            // 执行反向转移
            var result = await _market.TransferStockAsync(
                _toAccountId, 
                _accountId, 
                _symbol, 
                _quantity,
                isReversal: true,
                originalTradeId: _executionResult.TradeId);

            if (result.Success)
            {
                _logger.LogInformation("股票转移撤销成功: {TradeId}", result.TradeId);
            }
            else
            {
                _logger.LogWarning("股票转移撤销失败: {Message}", result.Message);
            }

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "撤销股票转移时出错");
            return TradeResult.Failed($"撤销股票转移出错: {ex.Message}");
        }
    }

    public override string GetType()
    {
        return "股票转移";
    }

    public override string GetDescription()
    {
        return $"Transfer {_quantity} shares of {_symbol} from {_accountId} to {_toAccountId}";
    }

    public override bool IsValid()
    {
        if (!base.IsValid())
            return false;

        // 转移特殊验证
        if (string.IsNullOrEmpty(_toAccountId))
        {
            _logger.LogWarning("目标账户ID不能为空");
            return false;
        }

        if (_accountId == _toAccountId)
        {
            _logger.LogWarning("源账户和目标账户不能相同");
            return false;
        }

        return true;
    }
}

// 10. 批量交易命令(宏命令)
public class BatchTradeCommand : ITradeCommand
{
    private readonly List<ITradeCommand> _commands = new List<ITradeCommand>();
    private readonly string _commandId;
    private readonly string _batchName;
    private readonly ILogger _logger;
    private readonly List<TradeResult> _results = new List<TradeResult>();

    public BatchTradeCommand(string batchName, ILogger logger)
    {
        _commandId = Guid.NewGuid().ToString();
        _batchName = batchName;
        _logger = logger;
    }

    public void AddCommand(ITradeCommand command)
    {
        _commands.Add(command);
    }

    public async Task<TradeResult> ExecuteAsync()
    {
        if (!IsValid())
        {
            return TradeResult.Failed("批量交易验证失败");
        }

        _logger.LogInformation("执行批量交易: {BatchName}, {Count} 笔交易", _batchName, _commands.Count);

        _results.Clear();
        bool allSuccess = true;
        StringBuilder messageBuilder = new StringBuilder();

        for (int i = 0; i < _commands.Count; i++)
        {
            ITradeCommand command = _commands[i];

            _logger.LogInformation("执行批量交易的第 {Index}/{Total} 笔: {Command}", 
                                   i + 1, _commands.Count, command.GetDescription());

            TradeResult result = await command.ExecuteAsync();
            _results.Add(result);

            if (!result.Success)
            {
                allSuccess = false;
                messageBuilder.AppendLine($"交易 {i + 1} 失败: {result.Message}");

                // 回滚已完成的交易
                await RollbackAsync(i - 1);
                break;
            }
        }

        if (allSuccess)
        {
            _logger.LogInformation("批量交易全部成功: {BatchName}", _batchName);
            return TradeResult.Successful(
                _commandId,
                0, // 批量交易没有单一价格
                _commands.Count,
                $"批量交易成功执行了 {_commands.Count} 笔交易");
        }
        else
        {
            _logger.LogWarning("批量交易部分失败: {BatchName}, {Message}", 
                               _batchName, messageBuilder.ToString());

            return TradeResult.Failed(messageBuilder.ToString());
        }
    }

    private async Task RollbackAsync(int lastSuccessIndex)
    {
        _logger.LogWarning("批量交易失败,回滚之前的 {Count} 笔交易", lastSuccessIndex + 1);

        // 从后往前回滚
        for (int i = lastSuccessIndex; i >= 0; i--)
        {
            ITradeCommand command = _commands[i];

            if (command.IsUndoable())
            {
                _logger.LogInformation("回滚批量交易的第 {Index} 笔: {Command}", 
                                       i + 1, command.GetDescription());

                await command.UndoAsync();
            }
            else
            {
                _logger.LogWarning("无法回滚批量交易的第 {Index} 笔: {Command}", 
                                   i + 1, command.GetDescription());
            }
        }
    }

    public async Task<TradeResult> UndoAsync()
    {
        _logger.LogInformation("撤销批量交易: {BatchName}", _batchName);

        bool allSuccess = true;
        StringBuilder messageBuilder = new StringBuilder();

        // 从后往前撤销
        for (int i = _commands.Count - 1; i >= 0; i--)
        {
            ITradeCommand command = _commands[i];

            if (command.IsUndoable())
            {
                _logger.LogInformation("撤销批量交易的第 {Index}/{Total} 笔: {Command}", 
                                       _commands.Count - i, _commands.Count, command.GetDescription());

                TradeResult result = await command.UndoAsync();

                if (!result.Success)
                {
                    allSuccess = false;
                    messageBuilder.AppendLine($"撤销交易 {_commands.Count - i} 失败: {result.Message}");
                }
            }
            else
            {
                _logger.LogWarning("批量交易的第 {Index}/{Total} 笔不可撤销: {Command}", 
                                   _commands.Count - i, _commands.Count, command.GetDescription());
            }
        }

        if (allSuccess)
        {
            _logger.LogInformation("批量交易撤销成功: {BatchName}", _batchName);
            return TradeResult.Successful(
                _commandId,
                0,
                _commands.Count,
                $"批量交易成功撤销了 {_commands.Count} 笔交易");
        }
        else
        {
            _logger.LogWarning("批量交易撤销部分失败: {BatchName}, {Message}", 
                               _batchName, messageBuilder.ToString());

            return TradeResult.Failed(messageBuilder.ToString());
        }
    }

    public string GetCommandId()
    {
        return _commandId;
    }

    public string GetType()
    {
        return "批量交易";
    }

    public string GetDescription()
    {
        return $"批量交易 '{_batchName}' 包含 {_commands.Count} 笔交易";
    }

    public bool IsUndoable()
    {
        // 批量交易只有在所有子命令都可撤销时才可撤销
        return _commands.All(cmd => cmd.IsUndoable());
    }

    public bool IsValid()
    {
        // 批量交易只有在所有子命令都有效时才有效
        if (_commands.Count == 0)
        {
            _logger.LogWarning("批量交易不包含任何交易");
            return false;
        }

        bool allValid = _commands.All(cmd => cmd.IsValid());

        if (!allValid)
        {
            _logger.LogWarning("批量交易包含无效的交易");
        }

        return allValid;
    }

    public List<ITradeCommand> GetCommands()
    {
        return new List<ITradeCommand>(_commands);
    }

    public int CommandCount => _commands.Count;
}

// 11. 接口 - 股票市场
public interface IStockMarket
{
    Task<StockQuote> GetQuoteAsync(string symbol);
    Task<TradeResult> ExecuteTradeAsync(
        string accountId, 
        string symbol, 
        int quantity, 
        decimal price, 
        TradeType tradeType, 
        OrderType orderType,
        bool isReversal = false,
        string originalTradeId = null);
    Task<TradeResult> CancelOrderAsync(string orderId);
    Task<TradeResult> TransferStockAsync(
        string fromAccountId, 
        string toAccountId, 
        string symbol, 
        int quantity,
        bool isReversal = false,
        string originalTradeId = null);
}

// 12. 股票报价类
public class StockQuote
{
    public string Symbol { get; set; }
    public decimal BidPrice { get; set; }
    public decimal AskPrice { get; set; }
    public decimal LastPrice { get; set; }
    public int BidSize { get; set; }
    public int AskSize { get; set; }
    public decimal DayHigh { get; set; }
    public decimal DayLow { get; set; }
    public long Volume { get; set; }
    public DateTime QuoteTime { get; set; }
}

// 13. 模拟股票市场实现
public class SimulatedStockMarket : IStockMarket
{
    private readonly Dictionary<string, StockQuote> _stockQuotes = new Dictionary<string, StockQuote>();
    private readonly Dictionary<string, Dictionary<string, int>> _portfolios = new Dictionary<string, Dictionary<string, int>>();
    private readonly Dictionary<string, TradeResult> _orderHistory = new Dictionary<string, TradeResult>();
    private readonly ILogger<SimulatedStockMarket> _logger;
    private readonly Random _random = new Random();

    public SimulatedStockMarket(ILogger<SimulatedStockMarket> logger)
    {
        _logger = logger;
        InitializeMarketData();
    }

    private void InitializeMarketData()
    {
        // 初始化一些模拟的股票报价
        _stockQuotes["AAPL"] = new StockQuote
        {
            Symbol = "AAPL",
            BidPrice = 150.25m,
            AskPrice = 150.50m,
            LastPrice = 150.30m,
            BidSize = 100,
            AskSize = 150,
            DayHigh = 152.50m,
            DayLow = 149.80m,
            Volume = 5000000,
            QuoteTime = DateTime.Now
        };

        _stockQuotes["MSFT"] = new StockQuote
        {
            Symbol = "MSFT",
            BidPrice = 310.75m,
            AskPrice = 311.00m,
            LastPrice = 310.80m,
            BidSize = 80,
            AskSize = 120,
            DayHigh = 312.50m,
            DayLow = 309.60m,
            Volume = 3500000,
            QuoteTime = DateTime.Now
        };

        _stockQuotes["GOOGL"] = new StockQuote
        {
            Symbol = "GOOGL",
            BidPrice = 2830.25m,
            AskPrice = 2830.75m,
            LastPrice = 2830.50m,
            BidSize = 50,
            AskSize = 60,
            DayHigh = 2835.00m,
            DayLow = 2825.50m,
            Volume = 1200000,
            QuoteTime = DateTime.Now
        };

        // 初始化一些模拟的投资组合
        _portfolios["ACC001"] = new Dictionary<string, int>
        {
            { "AAPL", 100 },
            { "MSFT", 50 },
            { "GOOGL", 10 }
        };

        _portfolios["ACC002"] = new Dictionary<string, int>
        {
            { "AAPL", 200 },
            { "MSFT", 0 },
            { "GOOGL", 5 }
        };
    }

    public async Task<StockQuote> GetQuoteAsync(string symbol)
    {
        await Task.Delay(100); // 模拟网络延迟

        if (_stockQuotes.TryGetValue(symbol, out StockQuote quote))
        {
            // 模拟价格略微变动
            decimal priceChange = (decimal)(_random.NextDouble() * 0.2 - 0.1);
            quote.LastPrice = Math.Round(quote.LastPrice * (1 + priceChange / 100), 2);
            quote.BidPrice = Math.Round(quote.LastPrice - 0.1m, 2);
            quote.AskPrice = Math.Round(quote.LastPrice + 0.1m, 2);
            quote.QuoteTime = DateTime.Now;

            return quote;
        }

        throw new Exception($"找不到股票代码: {symbol}");
    }

    public async Task<TradeResult> ExecuteTradeAsync(
        string accountId, 
        string symbol, 
        int quantity, 
        decimal price, 
        TradeType tradeType, 
        OrderType orderType,
        bool isReversal = false,
        string originalTradeId = null)
    {
        await Task.Delay(200); // 模拟处理延迟

        try
        {
            // 检查账户是否存在
            if (!_portfolios.ContainsKey(accountId))
            {
                _portfolios[accountId] = new Dictionary<string, int>();
            }

            var portfolio = _portfolios[accountId];

            // 检查股票是否存在
            if (!_stockQuotes.ContainsKey(symbol))
            {
                return TradeResult.Failed($"找不到股票代码: {symbol}");
            }

            // 执行交易的逻辑
            string tradeId = Guid.NewGuid().ToString();
            decimal executedPrice = price;

            // 对于市价单,使用当前报价
            if (orderType == OrderType.Market)
            {
                var quote = await GetQuoteAsync(symbol);
                executedPrice = tradeType == TradeType.Buy || tradeType == TradeType.BuyToCover
                    ? quote.AskPrice
                    : quote.BidPrice;
            }

            // 更新投资组合
            switch (tradeType)
            {
                case TradeType.Buy:
                case TradeType.BuyToCover:
                    if (!portfolio.ContainsKey(symbol))
                    {
                        portfolio[symbol] = 0;
                    }
                    portfolio[symbol] += quantity;
                    break;

                case TradeType.Sell:
                case TradeType.ShortSell:
                    if (!portfolio.ContainsKey(symbol) || portfolio[symbol] < quantity)
                    {
                        return TradeResult.Failed($"账户 {accountId} 没有足够的 {symbol} 股票");
                    }
                    portfolio[symbol] -= quantity;
                    break;

                case TradeType.Transfer:
                    // 转移在另一个方法中处理
                    break;
            }

            // 创建交易结果
            var result = TradeResult.Successful(tradeId, executedPrice, quantity);

            if (isReversal && !string.IsNullOrEmpty(originalTradeId))
            {
                result.AdditionalInfo["ReversalOf"] = originalTradeId;
            }

            // 记录交易历史
            _orderHistory[tradeId] = result;

            _logger.LogInformation("交易执行成功: {TradeId}, {TradeType} {Quantity} 股 {Symbol} 价格 {Price:C}", 
                                   tradeId, tradeType, quantity, symbol, executedPrice);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "执行交易时出错");
            return TradeResult.Failed($"执行交易出错: {ex.Message}");
        }
    }

    public async Task<TradeResult> CancelOrderAsync(string orderId)
    {
        await Task.Delay(150); // 模拟处理延迟

        if (_orderHistory.TryGetValue(orderId, out TradeResult order))
        {
            string cancelId = Guid.NewGuid().ToString();

            var result = TradeResult.Successful(
                cancelId,
                0,
                0,
                $"订单 {orderId} 已取消");

            result.AdditionalInfo["CancelledOrderId"] = orderId;

            _orderHistory[cancelId] = result;

            _logger.LogInformation("订单已取消: {OrderId}", orderId);

            return result;
        }

        return TradeResult.Failed($"找不到订单: {orderId}");
    }

    public async Task<TradeResult> TransferStockAsync(
        string fromAccountId, 
        string toAccountId, 
        string symbol, 
        int quantity,
        bool isReversal = false,
        string originalTradeId = null)
    {
        await Task.Delay(150); // 模拟处理延迟

        try
        {
            // 检查账户是否存在
            if (!_portfolios.ContainsKey(fromAccountId))
            {
                return TradeResult.Failed($"找不到源账户: {fromAccountId}");
            }    if (!_portfolios.ContainsKey(toAccountId))
            {
                _portfolios[toAccountId] = new Dictionary<string, int>();
            }

            var fromPortfolio = _portfolios[fromAccountId];
            var toPortfolio = _portfolios[toAccountId];

            // 检查股票是否存在
            if (!_stockQuotes.ContainsKey(symbol))
            {
                return TradeResult.Failed($"找不到股票代码: {symbol}");
            }

            // 检查源账户是否有足够的股票
            if (!fromPortfolio.ContainsKey(symbol) || fromPortfolio[symbol] < quantity)
            {
                return TradeResult.Failed($"账户 {fromAccountId} 没有足够的 {symbol} 股票");
            }

            // 执行转移
            fromPortfolio[symbol] -= quantity;

            if (!toPortfolio.ContainsKey(symbol))
            {
                toPortfolio[symbol] = 0;
            }

            toPortfolio[symbol] += quantity;

            // 创建交易结果
            string transferId = Guid.NewGuid().ToString();
            var currentQuote = await GetQuoteAsync(symbol);

            var result = TradeResult.Successful(
                transferId, 
                currentQuote.LastPrice, 
                quantity, 
                $"成功将 {quantity} 股 {symbol} 从账户 {fromAccountId} 转移到账户 {toAccountId}");

            if (isReversal && !string.IsNullOrEmpty(originalTradeId))
            {
                result.AdditionalInfo["ReversalOf"] = originalTradeId;
            }

            // 记录交易历史
            _orderHistory[transferId] = result;

            _logger.LogInformation("股票转移成功: {TransferId}, {Quantity} 股 {Symbol} 从账户 {FromAccount} 到 {ToAccount}", 
                                   transferId, quantity, symbol, fromAccountId, toAccountId);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "执行股票转移时出错");
            return TradeResult.Failed($"执行股票转移出错: {ex.Message}");
        }
    }

    // 用于测试和调试
    public Dictionary<string, int> GetPortfolio(string accountId)
    {
        if (_portfolios.TryGetValue(accountId, out var portfolio))
        {
            return new Dictionary<string, int>(portfolio);
        }

        return new Dictionary<string, int>();
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181

​

// 14. 命令处理器 - 调用者
public class TradeCommandProcessor
{
    private readonly Queue<ITradeCommand> _pendingCommands = new Queue<ITradeCommand>();
    private readonly Stack<ITradeCommand> _executedCommands = new Stack<ITradeCommand>();
    private readonly ILogger<TradeCommandProcessor> _logger;
    private bool _isProcessing = false;

    public TradeCommandProcessor(ILogger<TradeCommandProcessor> logger)
    {
        _logger = logger;
    }

    public void EnqueueCommand(ITradeCommand command)
    {
        _pendingCommands.Enqueue(command);
        _logger.LogInformation("命令已加入队列: {CommandType} {CommandId}", 
                               command.GetType(), command.GetCommandId());
    }

    public async Task ProcessNextCommandAsync()
    {
        if (_pendingCommands.Count == 0)
        {
            _logger.LogInformation("没有待处理的命令");
            return;
        }

        if (_isProcessing)
        {
            _logger.LogWarning("已有命令正在处理中,请稍后再试");
            return;
        }

        _isProcessing = true;

        try
        {
            ITradeCommand command = _pendingCommands.Dequeue();

            _logger.LogInformation("开始处理命令: {CommandType} {CommandId}", 
                                   command.GetType(), command.GetCommandId());

            if (!command.IsValid())
            {
                _logger.LogWarning("命令验证失败: {CommandType} {CommandId}", 
                                   command.GetType(), command.GetCommandId());
                return;
            }

            TradeResult result = await command.ExecuteAsync();

            if (result.Success)
            {
                _executedCommands.Push(command);
                _logger.LogInformation("命令执行成功: {CommandType} {CommandId}, 交易ID: {TradeId}", 
                                       command.GetType(), command.GetCommandId(), result.TradeId);
            }
            else
            {
                _logger.LogWarning("命令执行失败: {CommandType} {CommandId}, 原因: {Message}", 
                                   command.GetType(), command.GetCommandId(), result.Message);
            }
        }
        finally
        {
            _isProcessing = false;
        }
    }

    public async Task ProcessAllPendingCommandsAsync()
    {
        if (_isProcessing)
        {
            _logger.LogWarning("已有命令正在处理中,请稍后再试");
            return;
        }

        _isProcessing = true;

        try
        {
            _logger.LogInformation("开始处理所有待处理命令,数量: {Count}", _pendingCommands.Count);

            while (_pendingCommands.Count > 0)
            {
                ITradeCommand command = _pendingCommands.Dequeue();

                _logger.LogInformation("处理命令: {CommandType} {CommandId}", 
                                       command.GetType(), command.GetCommandId());

                if (!command.IsValid())
                {
                    _logger.LogWarning("命令验证失败: {CommandType} {CommandId}", 
                                       command.GetType(), command.GetCommandId());
                    continue;
                }

                TradeResult result = await command.ExecuteAsync();

                if (result.Success)
                {
                    _executedCommands.Push(command);
                    _logger.LogInformation("命令执行成功: {CommandType} {CommandId}, 交易ID: {TradeId}", 
                                           command.GetType(), command.GetCommandId(), result.TradeId);
                }
                else
                {
                    _logger.LogWarning("命令执行失败: {CommandType} {CommandId}, 原因: {Message}", 
                                       command.GetType(), command.GetCommandId(), result.Message);
                }
            }

            _logger.LogInformation("所有待处理命令已处理完成");
        }
        finally
        {
            _isProcessing = false;
        }
    }

    public async Task UndoLastCommandAsync()
    {
        if (_executedCommands.Count == 0)
        {
            _logger.LogInformation("没有可撤销的命令");
            return;
        }

        if (_isProcessing)
        {
            _logger.LogWarning("已有命令正在处理中,请稍后再试");
            return;
        }

        _isProcessing = true;

        try
        {
            ITradeCommand command = _executedCommands.Peek();

            if (!command.IsUndoable())
            {
                _logger.LogWarning("最后执行的命令不可撤销: {CommandType} {CommandId}", 
                                   command.GetType(), command.GetCommandId());
                return;
            }

            _logger.LogInformation("开始撤销命令: {CommandType} {CommandId}", 
                                   command.GetType(), command.GetCommandId());

            TradeResult result = await command.UndoAsync();

            if (result.Success)
            {
                _executedCommands.Pop(); // 只有撤销成功才从已执行栈中移除
                _logger.LogInformation("命令撤销成功: {CommandType} {CommandId}", 
                                       command.GetType(), command.GetCommandId());
            }
            else
            {
                _logger.LogWarning("命令撤销失败: {CommandType} {CommandId}, 原因: {Message}", 
                                   command.GetType(), command.GetCommandId(), result.Message);
            }
        }
        finally
        {
            _isProcessing = false;
        }
    }

    public int GetPendingCommandCount()
    {
        return _pendingCommands.Count;
    }

    public int GetExecutedCommandCount()
    {
        return _executedCommands.Count;
    }

    public ITradeCommand PeekLastExecutedCommand()
    {
        return _executedCommands.Count > 0 ? _executedCommands.Peek() : null;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// 15. 交易命令工厂
public class TradeCommandFactory
{
    private readonly IStockMarket _market;
    private readonly ILoggerFactory _loggerFactory;


    public TradeCommandFactory(IStockMarket market, ILoggerFactory loggerFactory)
    {
        _market = market;
        _loggerFactory = loggerFactory;
    }

    public ITradeCommand CreateMarketBuyCommand(string accountId, string symbol, int quantity)
    {
        return new MarketOrderCommand(
            accountId,
            symbol,
            quantity,
            TradeType.Buy,
            _market,
            _loggerFactory.CreateLogger<MarketOrderCommand>());
    }

    public ITradeCommand CreateMarketSellCommand(string accountId, string symbol, int quantity)
    {
        return new MarketOrderCommand(
            accountId,
            symbol,
            quantity,
            TradeType.Sell,
            _market,
            _loggerFactory.CreateLogger<MarketOrderCommand>());
    }

    public ITradeCommand CreateLimitBuyCommand(string accountId, string symbol, int quantity, decimal limitPrice)
    {
        return new LimitOrderCommand(
            accountId,
            symbol,
            quantity,
            limitPrice,
            TradeType.Buy,
            _market,
            _loggerFactory.CreateLogger<LimitOrderCommand>());
    }

    public ITradeCommand CreateLimitSellCommand(string accountId, string symbol, int quantity, decimal limitPrice)
    {
        return new LimitOrderCommand(
            accountId,
            symbol,
            quantity,
            limitPrice,
            TradeType.Sell,
            _market,
            _loggerFactory.CreateLogger<LimitOrderCommand>());
    }

    public ITradeCommand CreateStopLossCommand(string accountId, string symbol, int quantity, decimal stopPrice)
    {
        return new StopOrderCommand(
            accountId,
            symbol,
            quantity,
            stopPrice,
            TradeType.Sell,
            _market,
            _loggerFactory.CreateLogger<StopOrderCommand>());
    }

    public ITradeCommand CreateTransferCommand(string fromAccountId, string toAccountId, string symbol, int quantity)
    {
        return new TransferStockCommand(
            fromAccountId,
            toAccountId,
            symbol,
            quantity,
            _market,
            _loggerFactory.CreateLogger<TransferStockCommand>());
    }

    public BatchTradeCommand CreateBatchCommand(string batchName)
    {
        return new BatchTradeCommand(
            batchName,
            _loggerFactory.CreateLogger<BatchTradeCommand>());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// 16. 交易服务 - 外观类
public class TradingService
{
    private readonly TradeCommandProcessor _commandProcessor;
    private readonly TradeCommandFactory _commandFactory;
    private readonly IStockMarket _market;
    private readonly ILogger<TradingService> _logger;

    public TradingService(
        TradeCommandProcessor commandProcessor,
        TradeCommandFactory commandFactory,
        IStockMarket market,
        ILogger<TradingService> logger)
    {
        _commandProcessor = commandProcessor;
        _commandFactory = commandFactory;
        _market = market;
        _logger = logger;
    }

    public async Task<StockQuote> GetQuoteAsync(string symbol)
    {
        return await _market.GetQuoteAsync(symbol);
    }

    public void SubmitMarketBuy(string accountId, string symbol, int quantity)
    {
        _logger.LogInformation("提交市价买入: 账户 {AccountId}, {Quantity} 股 {Symbol}", 
                               accountId, quantity, symbol);

        var command = _commandFactory.CreateMarketBuyCommand(accountId, symbol, quantity);
        _commandProcessor.EnqueueCommand(command);
    }

    public void SubmitMarketSell(string accountId, string symbol, int quantity)
    {
        _logger.LogInformation("提交市价卖出: 账户 {AccountId}, {Quantity} 股 {Symbol}", 
                               accountId, quantity, symbol);

        var command = _commandFactory.CreateMarketSellCommand(accountId, symbol, quantity);
        _commandProcessor.EnqueueCommand(command);
    }

    public void SubmitLimitBuy(string accountId, string symbol, int quantity, decimal limitPrice)
    {
        _logger.LogInformation("提交限价买入: 账户 {AccountId}, {Quantity} 股 {Symbol}, 价格 {Price:C}", 
                               accountId, quantity, symbol, limitPrice);

        var command = _commandFactory.CreateLimitBuyCommand(accountId, symbol, quantity, limitPrice);
        _commandProcessor.EnqueueCommand(command);
    }

    public void SubmitLimitSell(string accountId, string symbol, int quantity, decimal limitPrice)
    {
        _logger.LogInformation("提交限价卖出: 账户 {AccountId}, {Quantity} 股 {Symbol}, 价格 {Price:C}", 
                               accountId, quantity, symbol, limitPrice);

        var command = _commandFactory.CreateLimitSellCommand(accountId, symbol, quantity, limitPrice);
        _commandProcessor.EnqueueCommand(command);
    }

    public void SubmitStopLoss(string accountId, string symbol, int quantity, decimal stopPrice)
    {
        _logger.LogInformation("提交止损单: 账户 {AccountId}, {Quantity} 股 {Symbol}, 触发价格 {Price:C}", 
                               accountId, quantity, symbol, stopPrice);

        var command = _commandFactory.CreateStopLossCommand(accountId, symbol, quantity, stopPrice);
        _commandProcessor.EnqueueCommand(command);
    }

    public void SubmitTransfer(string fromAccountId, string toAccountId, string symbol, int quantity)
    {
        _logger.LogInformation("提交股票转移: {Quantity} 股 {Symbol}, 从账户 {FromAccount} 到 {ToAccount}", 
                               quantity, symbol, fromAccountId, toAccountId);

        var command = _commandFactory.CreateTransferCommand(fromAccountId, toAccountId, symbol, quantity);
        _commandProcessor.EnqueueCommand(command);
    }

    public void SubmitPortfolioRebalance(string accountId, Dictionary<string, int> targetPortfolio)
    {
        _logger.LogInformation("提交投资组合再平衡: 账户 {AccountId}, {Count} 只股票", 
                               accountId, targetPortfolio.Count);

        // 获取当前投资组合
        var currentPortfolio = _market.GetPortfolio(accountId);

        // 创建批量命令
        var batchCommand = _commandFactory.CreateBatchCommand("Portfolio Rebalance");

        // 对比当前和目标投资组合,生成必要的交易命令
        foreach (var entry in targetPortfolio)
        {
            string symbol = entry.Key;
            int targetQuantity = entry.Value;

            int currentQuantity = currentPortfolio.ContainsKey(symbol) 
                ? currentPortfolio[symbol] 
                : 0;

            int difference = targetQuantity - currentQuantity;

            if (difference > 0)
            {
                // 需要买入
                batchCommand.AddCommand(_commandFactory.CreateMarketBuyCommand(
                    accountId, symbol, difference));
            }
            else if (difference < 0)
            {
                // 需要卖出
                batchCommand.AddCommand(_commandFactory.CreateMarketSellCommand(
                    accountId, symbol, -difference));
            }
        }

        // 处理当前持有但目标不包含的股票
        foreach (var entry in currentPortfolio)
        {
            string symbol = entry.Key;
            int currentQuantity = entry.Value;

            if (!targetPortfolio.ContainsKey(symbol) && currentQuantity > 0)
            {
                // 需要全部卖出
                batchCommand.AddCommand(_commandFactory.CreateMarketSellCommand(
                    accountId, symbol, currentQuantity));
            }
        }

        // 如果批量命令中有交易,则提交
        if (batchCommand.CommandCount > 0)
        {
            _commandProcessor.EnqueueCommand(batchCommand);
        }
        else
        {
            _logger.LogInformation("投资组合已经平衡,无需调整");
        }
    }

    public async Task ProcessNextCommandAsync()
    {
        await _commandProcessor.ProcessNextCommandAsync();
    }

    public async Task ProcessAllCommandsAsync()
    {
        await _commandProcessor.ProcessAllPendingCommandsAsync();
    }

    public async Task UndoLastTradeAsync()
    {
        await _commandProcessor.UndoLastCommandAsync();
    }

    public Dictionary<string, int> GetPortfolio(string accountId)
    {
        return _market.GetPortfolio(accountId);
    }

    public void PrintPortfolio(string accountId)
    {
        var portfolio = _market.GetPortfolio(accountId);

        _logger.LogInformation("账户 {AccountId} 的投资组合:", accountId);

        if (portfolio.Count == 0)
        {
            _logger.LogInformation("  (空)");
            return;
        }

        foreach (var entry in portfolio)
        {
            _logger.LogInformation("  {Symbol}: {Quantity} 股", entry.Key, entry.Value);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

​

// 17. 客户端代码
public class Program
{
    public static async Task Main()
    {
        // 设置依赖注入
        var services = new ServiceCollection();
        // 添加日志
        services.AddLogging(builder =>
                            {
                                builder.AddConsole();
                                builder.SetMinimumLevel(LogLevel.Information);
                            });

        // 注册服务
        services.AddSingleton<IStockMarket, SimulatedStockMarket>();
        services.AddSingleton<TradeCommandProcessor>();
        services.AddSingleton<TradeCommandFactory>();
        services.AddSingleton<TradingService>();

        var serviceProvider = services.BuildServiceProvider();

        // 获取交易服务
        var tradingService = serviceProvider.GetRequiredService<TradingService>();

        // 打印初始投资组合
        Console.WriteLine("=== 初始投资组合 ===");
        tradingService.PrintPortfolio("ACC001");

        // 获取股票报价
        var appleQuote = await tradingService.GetQuoteAsync("AAPL");
        Console.WriteLine($"\nAAPL 当前报价: 卖出价 {appleQuote.BidPrice:C}, 买入价 {appleQuote.AskPrice:C}, 最新成交价 {appleQuote.LastPrice:C}");

        // 提交一些交易命令
        Console.WriteLine("\n=== 提交交易命令 ===");

        // 1. 市价买入
        tradingService.SubmitMarketBuy("ACC001", "MSFT", 20);

        // 2. 限价卖出
        tradingService.SubmitLimitSell("ACC001", "AAPL", 30, 155.00m);

        // 3. 股票转移
        tradingService.SubmitTransfer("ACC001", "ACC002", "GOOGL", 5);

        // 处理命令
        Console.WriteLine("\n=== 处理交易命令 ===");
        await tradingService.ProcessAllCommandsAsync();

        // 打印更新后的投资组合
        Console.WriteLine("\n=== 更新后的投资组合 ===");
        tradingService.PrintPortfolio("ACC001");
        tradingService.PrintPortfolio("ACC002");

        // 提交批量交易
        Console.WriteLine("\n=== 提交投资组合再平衡 ===");
        tradingService.SubmitPortfolioRebalance("ACC001", new Dictionary<string, int>
                                                {
                                                    { "AAPL", 100 }, // 保持不变
                                                    { "MSFT", 100 }, // 增加
                                                    { "GOOGL", 0 },  // 减少到零
                                                    { "NFLX", 20 }   // 新增
                                                });

        // 处理命令
        await tradingService.ProcessAllCommandsAsync();

        // 打印再平衡后的投资组合
        Console.WriteLine("\n=== 再平衡后的投资组合 ===");
        tradingService.PrintPortfolio("ACC001");

        // 撤销最后一笔交易
        Console.WriteLine("\n=== 撤销最后一笔交易 ===");
        await tradingService.UndoLastTradeAsync();

        // 打印最终投资组合
        Console.WriteLine("\n=== 最终投资组合 ===");
        tradingService.PrintPortfolio("ACC001");
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

# 15. 迭代器模式

原理:
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露其内部表示。

思路:

  1. 定义迭代器接口,声明获取下一个元素、判断是否还有元素等方法
  2. 定义聚合接口,声明创建迭代器的方法
  3. 实现具体迭代器类,负责遍历聚合对象
  4. 实现具体聚合类,实现创建迭代器的方法

前辈经验:

  • 当你需要访问复杂数据结构而不暴露其内部细节时,使用迭代器模式
  • 迭代器提供统一的遍历接口,不同集合可以有不同的迭代器实现
  • C#提供了内置的迭代器支持(IEnumerable、IEnumerator接口和yield语句)
  • 迭代器可以支持不同的遍历策略(如正向、反向、过滤等)
  • 迭代器可以延迟计算元素,适用于处理大型集合

业务场景:
图书管理系统,需要以不同方式(如按作者、标题、出版日期等)迭代查询图书集合。

简单实现:

```csharp
// 图书类
public class Book
{
    public string Title { get; set; }
    public string Author { get; set; }
    public string ISBN { get; set; }
    public int Year { get; set; }
    
    public Book(string title, string author, string isbn, int year)
    {
        Title = title;
        Author = author;
        ISBN = isbn;
        Year = year;
    }
    
    public override string ToString()
    {
        return $"{Title} by {Author} ({Year}) - ISBN: {ISBN}";
    }
}

// 图书目录(使用C#内置迭代器模式)
public class BookCollection : IEnumerable<Book>
{
    private List<Book> _books = new List<Book>();
    
    public void AddBook(Book book)
    {
        _books.Add(book);
    }
    
    public void RemoveBook(Book book)
    {
        _books.Remove(book);
    }
    
    // 标准迭代器
    public IEnumerator<Book> GetEnumerator()
    {
        return _books.GetEnumerator();
    }
    
    // 非泛型迭代器
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    
    // 按年份迭代
    public IEnumerable<Book> GetBooksByYear()
    {
        List<Book> sortedBooks = new List<Book>(_books);
        sortedBooks.Sort((b1, b2) => b1.Year.CompareTo(b2.Year));
        
        foreach (Book book in sortedBooks)
        {
            yield return book;
        }
    }
    
    // 按作者迭代
    public IEnumerable<Book> GetBooksByAuthor()
    {
        List<Book> sortedBooks = new List<Book>(_books);
        sortedBooks.Sort((b1, b2) => string.Compare(b1.Author, b2.Author, StringComparison.Ordinal));
        
        foreach (Book book in sortedBooks)
        {
            yield return book;
        }
    }
    
    // 按标题迭代
    public IEnumerable<Book> GetBooksByTitle()
    {
        List<Book> sortedBooks = new List<Book>(_books);
        sortedBooks.Sort((b1, b2) => string.Compare(b1.Title, b2.Title, StringComparison.Ordinal));
        
        foreach (Book book in sortedBooks)
        {
            yield return book;
        }
    }
    
    // 按指定年份过滤
    public IEnumerable<Book> GetBooksPublishedAfter(int year)
    {
        foreach (Book book in _books)
        {
            if (book.Year > year)
            {
                yield return book;
            }
        }
    }
}

// 客户端代码
public class Client
{
    public static void Main()
    {
        // 创建图书集合
        BookCollection library = new BookCollection();
        
        // 添加一些图书
        library.AddBook(new Book("Design Patterns", "Erich Gamma et al.", "978-0201633610", 1994));
        library.AddBook(new Book("Clean Code", "Robert C. Martin", "978-0132350884", 2008));
        library.AddBook(new Book("Refactoring", "Martin Fowler", "978-0201485677", 1999));
        library.AddBook(new Book("Domain-Driven Design", "Eric Evans", "978-0321125217", 2003));
        library.AddBook(new Book("The Pragmatic Programmer", "Andrew Hunt", "978-0201616224", 1999));
        
        // 使用标准迭代器
        Console.WriteLine("=== 所有图书 ===");
        foreach (Book book in library)
        {
            Console.WriteLine(book);
        }
        
        // 按年份迭代
        Console.WriteLine("\n=== 按出版年份排序 ===");
        foreach (Book book in library.GetBooksByYear())
        {
            Console.WriteLine($"{book.Year}: {book.Title}");
        }
        
        // 按作者迭代
        Console.WriteLine("\n=== 按作者排序 ===");
        foreach (Book book in library.GetBooksByAuthor())
        {
            Console.WriteLine($"{book.Author}: {book.Title}");
        }
        
        // 按标题迭代
        Console.WriteLine("\n=== 按标题排序 ===");
        foreach (Book book in library.GetBooksByTitle())
        {
            Console.WriteLine(book.Title);
        }
        
        // 过滤迭代
        Console.WriteLine("\n=== 2000年后出版的图书 ===");
        foreach (Book book in library.GetBooksPublishedAfter(2000))
        {
            Console.WriteLine($"{book.Year}: {book.Title}");
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

复杂实现:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text;

// 1. 扩展图书类
public class Book
{
    // 基本属性
    public string ISBN { get; }
    public string Title { get; set; }
    public string Author { get; set; }
    public string Publisher { get; set; }
    public int Year { get; set; }
    public decimal Price { get; set; }
    public List<string> Categories { get; set; } = new List<string>();
    public int PageCount { get; set; }
    public string Language { get; set; }
    public double Rating { get; set; }
    public bool IsAvailable { get; set; } = true;
    public DateTime DateAdded { get; }
    
    // 构造函数
    public Book(string isbn, string title, string author, int year)
    {
        ISBN = isbn;
        Title = title;
        Author = author;
        Year = year;
        DateAdded = DateTime.Now;
    }
    
    // 扩展构造函数
    public Book(string isbn, string title, string author, string publisher, int year, 
        decimal price, int pageCount, string language, double rating = 0)
        : this(isbn, title, author, year)
    {
        Publisher = publisher;
        Price = price;
        PageCount = pageCount;
        Language = language;
        Rating = rating;
    }
    
    // 添加图书分类
    public void AddCategory(string category)
    {
        if (!Categories.Contains(category))
        {
            Categories.Add(category);
        }
    }
    
    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine($"Title: {Title}");
        sb.AppendLine($"Author: {Author}");
        sb.AppendLine($"ISBN: {ISBN}");
        sb.AppendLine($"Year: {Year}");
        sb.AppendLine($"Publisher: {Publisher}");
        sb.AppendLine($"Price: ${Price}");
        sb.AppendLine($"Pages: {PageCount}");
        sb.AppendLine($"Language: {Language}");
        sb.AppendLine($"Rating: {Rating}/5.0");
        sb.AppendLine($"Categories: {string.Join(", ", Categories)}");
        sb.AppendLine($"Available: {(IsAvailable ? "Yes" : "No")}");
        
        return sb.ToString();
    }
    
    // 简短描述
    public string GetShortDescription()
    {
        return $"{Title} by {Author} ({Year}) - {(IsAvailable ? "Available" : "Not Available")}";
    }
}

// 2. 自定义迭代器接口
public interface IBookIterator
{
    bool HasNext();
    Book Next();
    void Reset();
    string IteratorName { get; }
}

// 3. 具体迭代器 - 按标题迭代
public class TitleIterator : IBookIterator
{
    private readonly List<Book> _books;
    private int _position = -1;
    
    public string IteratorName => "Title Iterator";
    
    public TitleIterator(List<Book> books)
    {
        // 创建一个按标题排序的副本
        _books = new List<Book>(books);
        _books.Sort((b1, b2) => string.Compare(b1.Title, b2.Title, StringComparison.OrdinalIgnoreCase));
    }
    
    public bool HasNext()
    {
        return _position < _books.Count - 1;
    }
    
    public Book Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more books");
            
        return _books[++_position];
    }
    
    public void Reset()
    {
        _position = -1;
    }
}

// 4. 具体迭代器 - 按作者迭代
public class AuthorIterator : IBookIterator
{
    private readonly List<Book> _books;
    private int _position = -1;
    
    public string IteratorName => "Author Iterator";
    
    public AuthorIterator(List<Book> books)
    {
        // 创建一个按作者排序的副本
        _books = new List<Book>(books);
        _books.Sort((b1, b2) => string.Compare(b1.Author, b2.Author, StringComparison.OrdinalIgnoreCase));
    }
    
    public bool HasNext()
    {
        return _position < _books.Count - 1;
    }
    
    public Book Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more books");
            
        return _books[++_position];
    }
    
    public void Reset()
    {
        _position = -1;
    }
}

// 5. 具体迭代器 - 按年份迭代
public class YearIterator : IBookIterator
{
    private readonly List<Book> _books;
    private int _position = -1;
    
    public string IteratorName => "Year Iterator";
    
    public YearIterator(List<Book> books)
    {
        // 创建一个按年份排序的副本
        _books = new List<Book>(books);
        _books.Sort((b1, b2) => b1.Year.CompareTo(b2.Year));
    }
    
    public bool HasNext()
    {
        return _position < _books.Count - 1;
    }
    
    public Book Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more books");
            
        return _books[++_position];
    }
    
    public void Reset()
    {
        _position = -1;
    }
}

// 6. 具体迭代器 - 过滤迭代器
public class FilterIterator : IBookIterator
{
    private readonly List<Book> _books;
    private int _position = -1;
    private readonly Func<Book, bool> _predicate;
    private readonly string _filterDescription;
    
    public string IteratorName => $"Filter Iterator ({_filterDescription})";
    
    public FilterIterator(List<Book> books, Func<Book, bool> predicate, string filterDescription)
    {
        // 创建一个按过滤条件筛选的副本
        _books = books.Where(predicate).ToList();
        _predicate = predicate;
        _filterDescription = filterDescription;
    }
    
    public bool HasNext()
    {
        return _position < _books.Count - 1;
    }
    
    public Book Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more books");
            
        return _books[++_position];
    }
    
    public void Reset()
    {
        _position = -1;
    }
}

// 7. 具体迭代器 - 分类迭代器
public class CategoryIterator : IBookIterator
{
    private readonly List<Book> _books;
    private readonly string _category;
    private int _position = -1;
    
    public string IteratorName => $"Category Iterator ({_category})";
    
    public CategoryIterator(List<Book> books, string category)
    {
        _category = category;
        // 筛选特定分类的图书
        _books = books.Where(b => b.Categories.Contains(category)).ToList();
    }
    
    public bool HasNext()
    {
        return _position < _books.Count - 1;
    }
    
    public Book Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more books");
            
        return _books[++_position];
    }
    
    public void Reset()
    {
        _position = -1;
    }
}

// 8. 具体迭代器 - 分页迭代器
public class PaginatedIterator : IBookIterator
{
    private readonly List<Book> _books;
    private int _position = -1;
    private readonly int _pageSize;
    private readonly int _pageNumber;
    private readonly int _totalPages;
    
    public string IteratorName => $"Paginated Iterator (Page {_pageNumber} of {_totalPages}, {_pageSize} per page)";
    
    public PaginatedIterator(List<Book> books, int pageSize, int pageNumber)
    {
        _pageSize = pageSize;
        _pageNumber = pageNumber;
        
        // 计算总页数
        _totalPages = (int)Math.Ceiling((double)books.Count / pageSize);
        
        // 获取当前页的图书
        _books = books
            .Skip((pageNumber - 1) * pageSize)
            .Take(pageSize)
            .ToList();
    }
    
    public bool HasNext()
    {
        return _position < _books.Count - 1;
    }
    
    public Book Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more books");
            
        return _books[++_position];
    }
    
    public void Reset()
    {
        _position = -1;
    }
    
    public int GetPageNumber() => _pageNumber;
    public int GetTotalPages() => _totalPages;
}

// 9. 具体迭代器 - 复合迭代器
public class CompositeIterator : IBookIterator
{
    private readonly List<IBookIterator> _iterators;
    private int _currentIteratorIndex = 0;
    
    public string IteratorName => "Composite Iterator";
    
    public CompositeIterator(params IBookIterator[] iterators)
    {
        _iterators = new List<IBookIterator>(iterators);
    }
    
    public bool HasNext()
    {
        while (_currentIteratorIndex < _iterators.Count)
        {
            var currentIterator = _iterators[_currentIteratorIndex];
            if (currentIterator.HasNext())
            {
                return true;
            }
            _currentIteratorIndex++;
        }
        return false;
    }
    
    public Book Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more books");
            
        return _iterators[_currentIteratorIndex].Next();
    }
    
    public void Reset()
    {
        _currentIteratorIndex = 0;
        foreach (var iterator in _iterators)
        {
            iterator.Reset();
        }
    }
    
    public void AddIterator(IBookIterator iterator)
    {
        _iterators.Add(iterator);
    }
}

// 10. 高级迭代器 - 延迟加载迭代器
public class LazyLoadingIterator : IBookIterator
{
    private readonly Func<int, Book> _bookLoader;
    private readonly int _totalCount;
    private int _position = -1;
    private readonly Dictionary<int, Book> _loadedBooks = new Dictionary<int, Book>();
    
    public string IteratorName => "Lazy Loading Iterator";
    
    public LazyLoadingIterator(Func<int, Book> bookLoader, int totalCount)
    {
        _bookLoader = bookLoader;
        _totalCount = totalCount;
    }
    
    public bool HasNext()
    {
        return _position < _totalCount - 1;
    }
    
    public Book Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more books");
            
        _position++;
        
        // 检查是否已加载
        if (!_loadedBooks.ContainsKey(_position))
        {
            // 延迟加载图书
            _loadedBooks[_position] = _bookLoader(_position);
            Console.WriteLine($"Lazy loading book at position {_position}");
        }
        
        return _loadedBooks[_position];
    }
    
    public void Reset()
    {
        _position = -1;
    }
}

// 11. 集合接口
public interface IBookCollection
{
    void AddBook(Book book);
    void RemoveBook(string isbn);
    Book GetBook(string isbn);
    int Count { get; }
    IBookIterator CreateTitleIterator();
    IBookIterator CreateAuthorIterator();
    IBookIterator CreateYearIterator();
    IBookIterator CreateFilterIterator(Func<Book, bool> predicate, string description);
    IBookIterator CreateCategoryIterator(string category);
    IBookIterator CreatePaginatedIterator(int pageSize, int pageNumber);
}

// 12. 具体集合
public class BookCollection : IBookCollection
{
    private readonly List<Book> _books = new List<Book>();
    
    public void AddBook(Book book)
    {
        _books.Add(book);
    }
    
    public void RemoveBook(string isbn)
    {
        Book bookToRemove = _books.FirstOrDefault(b => b.ISBN == isbn);
        if (bookToRemove != null)
        {
            _books.Remove(bookToRemove);
        }
    }
    
    public Book GetBook(string isbn)
    {
        return _books.FirstOrDefault(b => b.ISBN == isbn);
    }
    
    public int Count => _books.Count;
    
    public IBookIterator CreateTitleIterator()
    {
        return new TitleIterator(_books);
    }
    
    public IBookIterator CreateAuthorIterator()
    {
        return new AuthorIterator(_books);
    }
    
    public IBookIterator CreateYearIterator()
    {
        return new YearIterator(_books);
    }
    
    public IBookIterator CreateFilterIterator(Func<Book, bool> predicate, string description)
    {
        return new FilterIterator(_books, predicate, description);
    }
    
    public IBookIterator CreateCategoryIterator(string category)
    {
        return new CategoryIterator(_books, category);
    }
    
    public IBookIterator CreatePaginatedIterator(int pageSize, int pageNumber)
    {
        return new PaginatedIterator(_books, pageSize, pageNumber);
    }
    
    // 支持LINQ的IEnumerable接口
    public IEnumerable<Book> AsEnumerable()
    {
        return _books.AsEnumerable();
    }
    
    // 创建复合迭代器
    public IBookIterator CreateCompositeIterator(params IBookIterator[] iterators)
    {
        return new CompositeIterator(iterators);
    }
    
    // 创建延迟加载迭代器
    public IBookIterator CreateLazyLoadingIterator()
    {
        return new LazyLoadingIterator(index =>
        {
            // 模拟从数据库加载单本图书
            System.Threading.Thread.Sleep(200); // 模拟延迟
            return index < _books.Count ? _books[index] : null;
        }, _books.Count);
    }
}

// 13. 图书馆管理系统
public class LibrarySystem
{
    private readonly IBookCollection _bookCollection;
    
    public LibrarySystem(IBookCollection bookCollection)
    {
        _bookCollection = bookCollection;
    }
    
    public void PrintBooks(IBookIterator iterator)
    {
        Console.WriteLine($"\n=== Using {iterator.IteratorName} ===");
        
        int count = 0;
        iterator.Reset();
        
        while (iterator.HasNext())
        {
            Book book = iterator.Next();
            Console.WriteLine($"{++count}. {book.GetShortDescription()}");
        }
        
        Console.WriteLine($"Total: {count} books");
    }
    
    public void PrintBookDetails(string isbn)
    {
        Book book = _bookCollection.GetBook(isbn);
        
        if (book != null)
        {
            Console.WriteLine("\n=== Book Details ===");
            Console.WriteLine(book);
        }
        else
        {
            Console.WriteLine($"Book with ISBN {isbn} not found.");
        }
    }
    
    public void SearchBooks(string keyword)
    {
        Console.WriteLine($"\n=== Search Results for '{keyword}' ===");
        
        var searchIterator = _bookCollection.CreateFilterIterator(
            book => book.Title.Contains(keyword, StringComparison.OrdinalIgnoreCase) || 
                   book.Author.Contains(keyword, StringComparison.OrdinalIgnoreCase),
            $"Search for '{keyword}'"
        );
        
        PrintBooks(searchIterator);
    }
    
    public void BrowseByCategory(string category)
    {
        var categoryIterator = _bookCollection.CreateCategoryIterator(category);
        PrintBooks(categoryIterator);
    }
    
    public void ListRecentlyAddedBooks(int count)
    {
        // 使用LINQ创建临时集合
        var recentBooks = _bookCollection.AsEnumerable()
            .OrderByDescending(b => b.DateAdded)
            .Take(count)
            .ToList();
            
        Console.WriteLine($"\n=== {count} Recently Added Books ===");
        
        int i = 1;
        foreach (var book in recentBooks)
        {
            Console.WriteLine($"{i++}. {book.GetShortDescription()} - Added: {book.DateAdded:yyyy-MM-dd}");
        }
    }
    
    public void BrowseCatalogByPages(int pageSize)
    {
        int currentPage = 1;
        bool keepBrowsing = true;
        
        while (keepBrowsing)
        {
            var paginatedIterator = _bookCollection.CreatePaginatedIterator(pageSize, currentPage);
            
            PrintBooks(paginatedIterator);
            
            int totalPages = ((PaginatedIterator)paginatedIterator).GetTotalPages();
            
            Console.WriteLine($"\nPage {currentPage} of {totalPages}");
            Console.Write("Enter 'n' for next page, 'p' for previous page, 'q' to quit: ");
            
            string input = Console.ReadLine().ToLower();
            
            switch (input)
            {
                case "n":
                    if (currentPage < totalPages)
                        currentPage++;
                    break;
                case "p":
                    if (currentPage > 1)
                        currentPage--;
                    break;
                case "q":
                    keepBrowsing = false;
                    break;
            }
        }
    }
}

// 14. 客户端代码
public class Client
{
    public static void Main()
    {
        // 创建图书集合
        IBookCollection library = new BookCollection();
        
        // 添加图书
        AddSampleBooks(library);
        
        // 创建图书馆系统
        LibrarySystem librarySystem = new LibrarySystem(library);
        
        // 使用不同的迭代器浏览图书
        librarySystem.PrintBooks(library.CreateTitleIterator());
        librarySystem.PrintBooks(library.CreateAuthorIterator());
        librarySystem.PrintBooks(library.CreateYearIterator());
        
        // 过滤迭代器 - 2000年后出版的图书
        var after2000Iterator = library.CreateFilterIterator(
            book => book.Year > 2000,
            "Published after 2000"
        );
        librarySystem.PrintBooks(after2000Iterator);
        
        // 过滤迭代器 - 高评分图书
        var highRatingIterator = library.CreateFilterIterator(
            book => book.Rating >= 4.5,
            "Rating >= 4.5"
        );
        librarySystem.PrintBooks(highRatingIterator);
        
        // 按分类浏览
        librarySystem.BrowseByCategory("Programming");
        
        // 搜索图书
        librarySystem.SearchBooks("Pattern");
        
        // 显示图书详情
        librarySystem.PrintBookDetails("978-0201633610");
        
        // 最近添加的图书
        librarySystem.ListRecentlyAddedBooks(3);
        
        // 分页浏览
        Console.WriteLine("\nPress Enter to start browsing by pages...");
        Console.ReadLine();
        librarySystem.BrowseCatalogByPages(3);
    }
    
    private static void AddSampleBooks(IBookCollection library)
    {
        // 创建并添加样本图书
        Book book1 = new Book("978-0201633610", "Design Patterns", "Erich Gamma et al.", "Addison-Wesley", 1994, 34.99m, 395, "English", 4.7);
        book1.AddCategory("Programming");
        book1.AddCategory("Software Engineering");
        library.AddBook(book1);
        
        Book book2 = new Book("978-0132350884", "Clean Code", "Robert C. Martin", "Prentice Hall", 2008, 29.99m, 464, "English", 4.8);
        book2.AddCategory("Programming");
        book2.AddCategory("Software Engineering");
        library.AddBook(book2);
        
        Book book3 = new Book("978-0201485677", "Refactoring", "Martin Fowler", "Addison-Wesley", 1999, 27.99m, 431, "English", 4.6);
        book3.AddCategory("Programming");
        book3.AddCategory("Software Engineering");
        library.AddBook(book3);
        
        Book book4 = new Book("978-0321125217", "Domain-Driven Design", "Eric Evans", "Addison-Wesley", 2003, 44.99m, 560, "English", 4.5);
        book4.AddCategory("Programming");
        book4.AddCategory("Software Architecture");
        library.AddBook(book4);
        
        Book book5 = new Book("978-0201616224", "The Pragmatic Programmer", "Andrew Hunt", "Addison-Wesley", 1999, 24.99m, 352, "English", 4.7);
        book5.AddCategory("Programming");
        book5.AddCategory("Software Engineering");
        library.AddBook(book5);
        
        Book book6 = new Book("978-0134757599", "Refactoring (2nd Edition)", "Martin Fowler", "Addison-Wesley", 2018, 34.99m, 448, "English", 4.9);
        book6.AddCategory("Programming");
        book6.AddCategory("Software Engineering");
        library.AddBook(book6);
        
        Book book7 = new Book("978-0596007126", "Head First Design Patterns", "Eric Freeman", "O'Reilly Media", 2004, 29.99m, 638, "English", 4.6);
        book7.AddCategory("Programming");
        book7.AddCategory("Software Engineering");
        library.AddBook(book7);
        
        Book book8 = new Book("978-1449373320", "Designing Data-Intensive Applications", "Martin Kleppmann", "O'Reilly Media", 2017, 39.99m, 616, "English", 4.8);
        book8.AddCategory("Database");
        book8.AddCategory("Software Architecture");
        library.AddBook(book8);
        
        Book book9 = new Book("978-0135957059", "The Software Craftsman", "Sandro Mancuso", "Prentice Hall", 2014, 29.99m, 256, "English", 4.5);
        book9.AddCategory("Programming");
        book9.AddCategory("Professional Development");
        library.AddBook(book9);
        
        Book book10 = new Book("978-0137081073", "The Clean Coder", "Robert C. Martin", "Prentice Hall", 2011, 24.99m, 256, "English", 4.6);
        book10.AddCategory("Programming");
        book10.AddCategory("Professional Development");
        library.AddBook(book10);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719

业务场景结合:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;

// 企业组织结构管理系统 - 使用迭代器模式遍历组织架构

// 1. 员工类
public class Employee
{
    public string Id { get; }
    public string Name { get; set; }
    public string Title { get; set; }
    public string Department { get; set; }
    public decimal Salary { get; set; }
    public int Level { get; set; }
    public DateTime HireDate { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
    public Employee Manager { get; set; }
    public string Location { get; set; }
    public List<string> Skills { get; set; } = new List<string>();
    public Dictionary<string, string> Attributes { get; set; } = new Dictionary<string, string>();
    
    public Employee(string id, string name, string title, string department)
    {
        Id = id;
        Name = name;
        Title = title;
        Department = department;
        HireDate = DateTime.Now;
    }
    
    public void AddSkill(string skill)
    {
        if (!Skills.Contains(skill))
        {
            Skills.Add(skill);
        }
    }
    
    public void AddAttribute(string key, string value)
    {
        Attributes[key] = value;
    }
    
    public override string ToString()
    {
        return $"{Name} - {Title} ({Department})";
    }
    
    public string GetDetailedInfo()
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine($"ID: {Id}");
        sb.AppendLine($"Name: {Name}");
        sb.AppendLine($"Title: {Title}");
        sb.AppendLine($"Department: {Department}");
        sb.AppendLine($"Level: {Level}");
        sb.AppendLine($"Manager: {Manager?.Name ?? "None"}");
        sb.AppendLine($"Hire Date: {HireDate:yyyy-MM-dd}");
        sb.AppendLine($"Salary: ${Salary:N0}");
        sb.AppendLine($"Email: {Email}");
        sb.AppendLine($"Phone: {Phone}");
        sb.AppendLine($"Location: {Location}");
        sb.AppendLine($"Skills: {string.Join(", ", Skills)}");
        
        return sb.ToString();
    }
}

// 2. 部门类
public class Department
{
    public string Id { get; }
    public string Name { get; set; }
    public Employee Manager { get; set; }
    public Department ParentDepartment { get; set; }
    public List<Department> SubDepartments { get; set; } = new List<Department>();
    public List<Employee> Employees { get; set; } = new List<Employee>();
    public string Location { get; set; }
    public string Description { get; set; }
    public DateTime CreatedDate { get; set; }
    
    public Department(string id, string name)
    {
        Id = id;
        Name = name;
        CreatedDate = DateTime.Now;
    }
    
    public void AddEmployee(Employee employee)
    {
        if (!Employees.Contains(employee))
        {
            Employees.Add(employee);
            employee.Department = Name;
        }
    }
    
    public void RemoveEmployee(Employee employee)
    {
        Employees.Remove(employee);
    }
    
    public void AddSubDepartment(Department department)
    {
        if (!SubDepartments.Contains(department))
        {
            SubDepartments.Add(department);
            department.ParentDepartment = this;
        }
    }
    
    public override string ToString()
    {
        return $"{Name} (Employees: {Employees.Count}, Sub-departments: {SubDepartments.Count})";
    }
}

// 3. 组织机构类
public class Organization
{
    public string Name { get; set; }
    public string Description { get; set; }
    public Department RootDepartment { get; set; }
    public List<Employee> AllEmployees { get; private set; } = new List<Employee>();
    public List<Department> AllDepartments { get; private set; } = new List<Department>();
    
    public Organization(string name, string description = "")
    {
        Name = name;
        Description = description;
    }
    
    public void SetRootDepartment(Department department)
    {
        RootDepartment = department;
        RefreshDepartments();
    }
    
    public void RefreshDepartments()
    {
        // 刷新部门和员工列表
        AllDepartments.Clear();
        AllEmployees.Clear();
        
        if (RootDepartment != null)
        {
            // 递归收集所有部门
            CollectDepartments(RootDepartment);
        }
    }
    
    private void CollectDepartments(Department department)
    {
        AllDepartments.Add(department);
        AllEmployees.AddRange(department.Employees);
        
        foreach (var subDepartment in department.SubDepartments)
        {
            CollectDepartments(subDepartment);
        }
    }
    
    public int GetTotalEmployeeCount()
    {
        return AllEmployees.Count;
    }
    
    public int GetTotalDepartmentCount()
    {
        return AllDepartments.Count;
    }
    
    public Employee FindEmployeeById(string id)
    {
        return AllEmployees.FirstOrDefault(e => e.Id == id);
    }
    
    public Department FindDepartmentById(string id)
    {
        return AllDepartments.FirstOrDefault(d => d.Id == id);
    }
}

// 4. 迭代器接口
public interface IOrganizationIterator<T>
{
    bool HasNext();
    T Next();
    void Reset();
    string IteratorName { get; }
}

// 5. 员工迭代器接口
public interface IEmployeeIterator : IOrganizationIterator<Employee>
{
}

// 6. 部门迭代器接口
public interface IDepartmentIterator : IOrganizationIterator<Department>
{
}

// 7. 具体员工迭代器 - 按部门迭代
public class EmployeesByDepartmentIterator : IEmployeeIterator
{
    private readonly Organization _organization;
    private readonly Queue<Department> _departmentsToProcess;
    private readonly List<Employee> _processedEmployees;
    private int _currentEmployeeIndex = -1;
    
    public string IteratorName => "Employees By Department Iterator";
    
    public EmployeesByDepartmentIterator(Organization organization)
    {
        _organization = organization;
        _departmentsToProcess = new Queue<Department>();
        _processedEmployees = new List<Employee>();
        
        Reset();
    }
    
    public bool HasNext()
    {
        ProcessNextDepartmentIfNeeded();
        return _currentEmployeeIndex < _processedEmployees.Count - 1;
    }
    
    public Employee Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more employees");
            
        return _processedEmployees[++_currentEmployeeIndex];
    }
    
    public void Reset()
    {
        _departmentsToProcess.Clear();
        _processedEmployees.Clear();
        _currentEmployeeIndex = -1;
        
        if (_organization.RootDepartment != null)
        {
            _departmentsToProcess.Enqueue(_organization.RootDepartment);
        }
    }
    
    private void ProcessNextDepartmentIfNeeded()
    {
        // 如果还有员工可处理,无需加载新部门
        if (_currentEmployeeIndex < _processedEmployees.Count - 1)
            return;
            
        // 处理下一个部门
        while (_departmentsToProcess.Count > 0)
        {
            Department department = _departmentsToProcess.Dequeue();
            
            // 添加当前部门的员工
            _processedEmployees.AddRange(department.Employees);
            
            // 将子部门加入队列
            foreach (var subDepartment in department.SubDepartments)
            {
                _departmentsToProcess.Enqueue(subDepartment);
            }
            
            // 如果已经有员工了,可以返回
            if (_processedEmployees.Count > 0)
                break;
        }
    }
}

// 8. 具体员工迭代器 - 按级别迭代
public class EmployeesByLevelIterator : IEmployeeIterator
{
    private readonly List<Employee> _employees;
    private int _position = -1;
    
    public string IteratorName => "Employees By Level Iterator";
    
    public EmployeesByLevelIterator(Organization organization)
    {
        // 按级别排序
        _employees = new List<Employee>(organization.AllEmployees);
        _employees.Sort((e1, e2) => e2.Level.CompareTo(e1.Level)); // 降序排列,级别高的先
    }
    
    public bool HasNext()
    {
        return _position < _employees.Count - 1;
    }
    
    public Employee Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more employees");
            
        return _employees[++_position];
    }
    
    public void Reset()
    {
        _position = -1;
    }
}

// 9. 具体员工迭代器 - 按薪资迭代
public class EmployeesBySalaryIterator : IEmployeeIterator
{
    private readonly List<Employee> _employees;
    private int _position = -1;
    
    public string IteratorName => "Employees By Salary Iterator";
    
    public EmployeesBySalaryIterator(Organization organization)
    {
        // 按薪资排序
        _employees = new List<Employee>(organization.AllEmployees);
        _employees.Sort((e1, e2) => e2.Salary.CompareTo(e1.Salary)); // 降序排列,薪资高的先
    }
    
    public bool HasNext()
    {
        return _position < _employees.Count - 1;
    }
    
    public Employee Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more employees");
            
        return _employees[++_position];
    }
    
    public void Reset()
    {
        _position = -1;
    }
}

// 10. 具体员工迭代器 - 按入职时间迭代
public class EmployeesByHireDateIterator : IEmployeeIterator
{
    private readonly List<Employee> _employees;
    private int _position = -1;
    
    public string IteratorName => "Employees By Hire Date Iterator";
    
    public EmployeesByHireDateIterator(Organization organization)
    {
        // 按入职时间排序
        _employees = new List<Employee>(organization.AllEmployees);
        _employees.Sort((e1, e2) => e1.HireDate.CompareTo(e2.HireDate)); // 升序排列,入职早的先
    }
    
    public bool HasNext()
    {
        return _position < _employees.Count - 1;
    }
    
    public Employee Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more employees");
            
        return _employees[++_position];
    }
    
    public void Reset()
    {
        _position = -1;
    }
}

// 11. 具体部门迭代器 - 深度优先
public class DepartmentDepthFirstIterator : IDepartmentIterator
{
    private readonly Organization _organization;
    private readonly Stack<Department> _stack = new Stack<Department>();
    private readonly HashSet<string> _visited = new HashSet<string>();
    
    public string IteratorName => "Department Depth-First Iterator";
    
    public DepartmentDepthFirstIterator(Organization organization)
    {
        _organization = organization;
        Reset();
    }
    
    public bool HasNext()
    {
        return _stack.Count > 0;
    }
    
    public Department Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more departments");
            
        Department current = _stack.Pop();
        _visited.Add(current.Id);
        
        // 将子部门压入栈中,以便后续访问
        foreach (var subDept in current.SubDepartments)
        {
            if (!_visited.Contains(subDept.Id))
            {
                _stack.Push(subDept);
            }
        }
        
        return current;
    }
    
    public void Reset()
    {
        _stack.Clear();
        _visited.Clear();
        
        if (_organization.RootDepartment != null)
        {
            _stack.Push(_organization.RootDepartment);
        }
    }
}

// 12. 具体部门迭代器 - 广度优先
public class DepartmentBreadthFirstIterator : IDepartmentIterator
{
    private readonly Organization _organization;
    private readonly Queue<Department> _queue = new Queue<Department>();
    private readonly HashSet<string> _visited = new HashSet<string>();
    
    public string IteratorName => "Department Breadth-First Iterator";
    
    public DepartmentBreadthFirstIterator(Organization organization)
    {
        _organization = organization;
        Reset();
    }
    
    public bool HasNext()
    {
        return _queue.Count > 0;
    }
    
    public Department Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more departments");
            
        Department current = _queue.Dequeue();
        _visited.Add(current.Id);
        
        // 将子部门加入队列,以便后续访问
        foreach (var subDept in current.SubDepartments)
        {
            if (!_visited.Contains(subDept.Id))
            {
                _queue.Enqueue(subDept);
            }
        }
        
        return current;
    }
    
    public void Reset()
    {
        _queue.Clear();
        _visited.Clear();
        
        if (_organization.RootDepartment != null)
        {
            _queue.Enqueue(_organization.RootDepartment);
        }
    }
}

// 13. 过滤迭代器 - 员工
public class FilteredEmployeeIterator : IEmployeeIterator
{
    private readonly List<Employee> _filteredEmployees;
    private int _position = -1;
    private readonly string _filterDescription;
    
    public string IteratorName => $"Filtered Employee Iterator ({_filterDescription})";
    
    public FilteredEmployeeIterator(IEnumerable<Employee> employees, Func<Employee, bool> predicate, string filterDescription)
    {
        _filteredEmployees = employees.Where(predicate).ToList();
        _filterDescription = filterDescription;
    }
    
    public bool HasNext()
    {
        return _position < _filteredEmployees.Count - 1;
    }
    
    public Employee Next()
    {
        if (!HasNext())
            throw new InvalidOperationException("No more employees");
            
        return _filteredEmployees[++_position];
    }
    
    public void Reset()
    {
        _position = -1;
    }
}

// 14. 迭代器创建工厂
public class OrganizationIteratorFactory
{
    private readonly Organization _organization;
    private readonly ILogger<OrganizationIteratorFactory> _logger;
    
    public OrganizationIteratorFactory(Organization organization, ILogger<OrganizationIteratorFactory> logger)
    {
        _organization = organization;
        _logger = logger;
    }
    
    // 员工迭代器
    public IEmployeeIterator CreateEmployeesByDepartmentIterator()
    {
        _logger.LogInformation("Creating employees by department iterator");
        return new EmployeesByDepartmentIterator(_organization);
    }
    
    public IEmployeeIterator CreateEmployeesByLevelIterator()
    {
        _logger.LogInformation("Creating employees by level iterator");
        return new EmployeesByLevelIterator(_organization);
    }
    
    public IEmployeeIterator CreateEmployeesBySalaryIterator()
    {
        _logger.LogInformation("Creating employees by salary iterator");
        return new EmployeesBySalaryIterator(_organization);
    }
    
    public IEmployeeIterator CreateEmployeesByHireDateIterator()
    {
        _logger.LogInformation("Creating employees by hire date iterator");
        return new EmployeesByHireDateIterator(_organization);
    }
    
    public IEmployeeIterator CreateFilteredEmployeeIterator(Func<Employee, bool> predicate, string description)
    {
        _logger.LogInformation($"Creating filtered employee iterator: {description}");
        return new FilteredEmployeeIterator(_organization.AllEmployees, predicate, description);
    }
    
    // 部门迭代器
    public IDepartmentIterator CreateDepartmentDepthFirstIterator()
    {
        _logger.LogInformation("Creating department depth-first iterator");
        return new DepartmentDepthFirstIterator(_organization);
    }
    
    public IDepartmentIterator CreateDepartmentBreadthFirstIterator()
    {
        _logger.LogInformation("Creating department breadth-first iterator");
        return new DepartmentBreadthFirstIterator(_organization);
    }
}

// 15. 组织结构分析器
public class OrganizationAnalyzer
{
    private readonly Organization _organization;
    private readonly OrganizationIteratorFactory _iteratorFactory;
    private readonly ILogger<OrganizationAnalyzer> _logger;
    
    public OrganizationAnalyzer(
        Organization organization, 
        OrganizationIteratorFactory iteratorFactory,
        ILogger<OrganizationAnalyzer> logger)
    {
        _organization = organization;
        _iteratorFactory = iteratorFactory;
        _logger = logger;
    }
    
    public void PrintOrganizationSummary()
    {
        _logger.LogInformation("Generating organization summary");
        
        Console.WriteLine($"\n=== {_organization.Name} Organization Summary ===");
        Console.WriteLine($"Total Departments: {_organization.GetTotalDepartmentCount()}");
        Console.WriteLine($"Total Employees: {_organization.GetTotalEmployeeCount()}");
        Console.WriteLine($"Description: {_organization.Description}");
    }
    
    public void PrintDepartmentHierarchy()
    {
        _logger.LogInformation("Printing department hierarchy");
        
        Console.WriteLine("\n=== Department Hierarchy ===");
        
        IDepartmentIterator iterator = _iteratorFactory.CreateDepartmentDepthFirstIterator();
        PrintDepartmentsWithIndentation(iterator);
    }
    
    private void PrintDepartmentsWithIndentation(IDepartmentIterator iterator)
    {
        Dictionary<string, int> depthMap = new Dictionary<string, int>();
        CalculateDepartmentDepth(_organization.RootDepartment, 0, depthMap);
        
        iterator.Reset();
        while (iterator.HasNext())
        {
            Department dept = iterator.Next();
            int depth = depthMap.ContainsKey(dept.Id) ? depthMap[dept.Id] : 0;
            string indent = new string(' ', depth * 2);
            
            Console.WriteLine($"{indent}- {dept.Name} ({dept.Employees.Count} employees)");
        }
    }
    
    private void CalculateDepartmentDepth(Department department, int depth, Dictionary<string, int> depthMap)
    {
        depthMap[department.Id] = depth;
        
        foreach (var subDept in department.SubDepartments)
        {
            CalculateDepartmentDepth(subDept, depth + 1, depthMap);
        }
    }
    
    public void PrintEmployeesByDepartment()
    {
        _logger.LogInformation("Printing employees grouped by department");
        
        Console.WriteLine("\n=== Employees By Department ===");
        
        IEmployeeIterator iterator = _iteratorFactory.CreateEmployeesByDepartmentIterator();
        PrintEmployees(iterator);
    }
    
    public void PrintEmployeesByLevel()
    {
        _logger.LogInformation("Printing employees by level");
        
        Console.WriteLine("\n=== Employees By Level ===");
        
        IEmployeeIterator iterator = _iteratorFactory.CreateEmployeesByLevelIterator();
        PrintEmployees(iterator);
    }
    
    public void PrintEmployeesBySalary()
    {
        _logger.LogInformation("Printing employees by salary");
        
        Console.WriteLine("\n=== Employees By Salary ===");
        
        IEmployeeIterator iterator = _iteratorFactory.CreateEmployeesBySalaryIterator();
        
        iterator.Reset();
        int count = 1;
        
        while (iterator.HasNext())
        {
            Employee employee = iterator.Next();
            Console.WriteLine($"{count++}. {employee.Name} - {employee.Title} (${employee.Salary:N0})");
        }
    }
    
    public void PrintEmployeesByHireDate()
    {
        _logger.LogInformation("Printing employees by hire date");
        
        Console.WriteLine("\n=== Employees By Hire Date ===");
        
        IEmployeeIterator iterator = _iteratorFactory.CreateEmployeesByHireDateIterator();
        
        iterator.Reset();
        int count = 1;
        
        while (iterator.HasNext())
        {
            Employee employee = iterator.Next();
            Console.WriteLine($"{count++}. {employee.Name} - Hired: {employee.HireDate:yyyy-MM-dd}");
        }
    }
    
    public void PrintSeniorManagement()
    {
        _logger.LogInformation("Printing senior management (level >= 8)");
        
        Console.WriteLine("\n=== Senior Management (Level >= 8) ===");
        
        IEmployeeIterator iterator = _iteratorFactory.CreateFilteredEmployeeIterator(
            e => e.Level >= 8,
            "Senior Management"
        );
        
        PrintEmployees(iterator);
    }
    
    public void PrintRecentHires(int months)
    {
        _logger.LogInformation($"Printing employees hired in the last {months} months");
        
        Console.WriteLine($"\n=== Recent Hires (Last {months} Months) ===");
        
        DateTime cutoffDate = DateTime.Now.AddMonths(-months);
        
        IEmployeeIterator iterator = _iteratorFactory.CreateFilteredEmployeeIterator(
            e => e.HireDate >= cutoffDate,
            $"Hired after {cutoffDate:yyyy-MM-dd}"
        );
        
        PrintEmployees(iterator);
    }
    
    public void PrintEmployeesByLocation(string location)
    {
        _logger.LogInformation($"Printing employees at location: {location}");
        
        Console.WriteLine($"\n=== Employees at {location} ===");
        
        IEmployeeIterator iterator = _iteratorFactory.CreateFilteredEmployeeIterator(
            e => e.Location == location,
            $"Location: {location}"
        );
        
        PrintEmployees(iterator);
    }
    
    public void PrintEmployeesWithSkill(string skill)
    {
        _logger.LogInformation($"Printing employees with skill: {skill}");
        
        Console.WriteLine($"\n=== Employees with {skill} Skill ===");
        
        IEmployeeIterator iterator = _iteratorFactory.CreateFilteredEmployeeIterator(
            e => e.Skills.Contains(skill),
            $"Has skill: {skill}"
        );
        
        PrintEmployees(iterator);
    }
    
    private void PrintEmployees(IEmployeeIterator iterator)
    {
        iterator.Reset();
        int count = 1;
        
        while (iterator.HasNext())
        {
            Employee employee = iterator.Next();
            Console.WriteLine($"{count++}. {employee}");
        }
        
        if (count == 1)
        {
            Console.WriteLine("No employees found.");
        }
    }
    
    public void PrintDepartmentDetails(string departmentId)
    {
        Department department = _organization.FindDepartmentById(departmentId);
        
        if (department == null)
        {
            Console.WriteLine($"Department with ID {departmentId} not found.");
            return;
        }
        
        Console.WriteLine($"\n=== Department Details: {department.Name} ===");
        Console.WriteLine($"ID: {department.Id}");
        Console.WriteLine($"Manager: {department.Manager?.Name ?? "None"}");
        Console.WriteLine($"Location: {department.Location}");
        Console.WriteLine($"Description: {department.Description}");
        Console.WriteLine($"Parent Department: {department.ParentDepartment?.Name ?? "None"}");
        Console.WriteLine($"Number of Employees: {department.Employees.Count}");
        Console.WriteLine($"Number of Sub-departments: {department.SubDepartments.Count}");
        
        if (department.SubDepartments.Count > 0)
        {
            Console.WriteLine("\nSub-departments:");
            foreach (var subDept in department.SubDepartments)
            {
                Console.WriteLine($"- {subDept.Name}");
            }
        }
        
        if (department.Employees.Count > 0)
        {
            Console.WriteLine("\nEmployees:");
            int count = 1;
            foreach (var employee in department.Employees)
            {
                Console.WriteLine($"{count++}. {employee.Name} - {employee.Title}");
            }
        }
    }
    
    public void PrintEmployeeDetails(string employeeId)
    {
        Employee employee = _organization.FindEmployeeById(employeeId);
        
        if (employee == null)
        {
            Console.WriteLine($"Employee with ID {employeeId} not found.");
            return;
        }
        
        Console.WriteLine($"\n=== Employee Details ===");
        Console.WriteLine(employee.GetDetailedInfo());
    }
}

// 16. 客户端代码
public class Program
{
    public static void Main()
    {
        // 设置依赖注入
        var services = new ServiceCollection();
        
        // 添加日志
        services.AddLogging(builder =>
        {
            builder.AddConsole();
        });
        
        // 创建组织结构
        Organization organization = new Organization("TechCorp", "A technology company");
        
        // 填充组织结构
        InitializeOrganization(organization);
        
        // 注册服务
        services.AddSingleton(organization);
        services.AddSingleton<OrganizationIteratorFactory>();
        services.AddSingleton<OrganizationAnalyzer>();
        
        var serviceProvider = services.BuildServiceProvider();
        
        // 获取分析器
        var analyzer = serviceProvider.GetRequiredService<OrganizationAnalyzer>();
        
        // 生成各种报表
        analyzer.PrintOrganizationSummary();
        analyzer.PrintDepartmentHierarchy();
        analyzer.PrintEmployeesByDepartment();
        analyzer.PrintEmployeesByLevel();
        analyzer.PrintEmployeesBySalary();
        analyzer.PrintEmployeesByHireDate();
        analyzer.PrintSeniorManagement();
        analyzer.PrintRecentHires(6);
        analyzer.PrintEmployeesByLocation("New York");
        analyzer.PrintEmployeesWithSkill("Leadership");
        
        // 输出特定部门详情
        analyzer.PrintDepartmentDetails("DEPT-001"); // 工程部
        
        // 输出特定员工详情
        analyzer.PrintEmployeeDetails("EMP-001"); // CEO
    }
    
    private static void InitializeOrganization(Organization organization)
    {
        // 创建部门
        Department rootDept = new Department("DEPT-000", "Executive");
        rootDept.Location = "Headquarters";
        rootDept.Description = "Executive leadership team";
        
        Department engineeringDept = new Department("DEPT-001", "Engineering");
        engineeringDept.Location = "San Francisco";
        engineeringDept.Description = "Product development and engineering";
        
        Department marketingDept = new Department("DEPT-002", "Marketing");
        marketingDept.Location = "New York";
        marketingDept.Description = "Marketing and communications";
        
        Department hrDept = new Department("DEPT-003", "Human Resources");
        hrDept.Location = "Chicago";
        hrDept.Description = "HR and recruitment";
        
        Department financeDept = new Department("DEPT-004", "Finance");
        financeDept.Location = "New York";
        financeDept.Description = "Finance and accounting";
        
        // 创建子部门
        Department softwareDept = new Department("DEPT-001-1", "Software Development");
        softwareDept.Location = "San Francisco";
        softwareDept.Description = "Software development teams";
        
        Department qaTestingDept = new Department("DEPT-001-2", "QA & Testing");
        qaTestingDept.Location = "San Francisco";
        qaTestingDept.Description = "Quality assurance and testing";
        
        Department infraDept = new Department("DEPT-001-3", "Infrastructure");
        infraDept.Location = "Seattle";
        infraDept.Description = "IT infrastructure and operations";
        
        // 构建部门层次结构
        rootDept.AddSubDepartment(engineeringDept);
        rootDept.AddSubDepartment(marketingDept);
        rootDept.AddSubDepartment(hrDept);
        rootDept.AddSubDepartment(financeDept);
        
        engineeringDept.AddSubDepartment(softwareDept);
        engineeringDept.AddSubDepartment(qaTestingDept);
        engineeringDept.AddSubDepartment(infraDept);
        
        // 创建员工
        Employee ceo = new Employee("EMP-001", "John Smith", "CEO", "Executive");
        ceo.Salary = 350000;
        ceo.Level = 10;
        ceo.HireDate = DateTime.Now.AddYears(-5);
        ceo.Email = "john.smith@techcorp.com";
        ceo.Phone = "555-123-4567";
        ceo.Location = "Headquarters";
        ceo.AddSkill("Leadership");
        ceo.AddSkill("Strategic Planning");
        ceo.AddSkill("Business Development");
        
        Employee cto = new Employee("EMP-002", "Emily Johnson", "CTO", "Engineering");
        cto.Salary = 280000;
        cto.Level = 9;
        cto.HireDate = DateTime.Now.AddYears(-4);
        cto.Email = "emily.johnson@techcorp.com";
        cto.Phone = "555-234-5678";
        cto.Location = "San Francisco";
        cto.Manager = ceo;
        cto.AddSkill("Technical Leadership");
        cto.AddSkill("Software Architecture");
        cto.AddSkill("Strategic Planning");
        
        Employee cmo = new Employee("EMP-003", "Michael Brown", "CMO", "Marketing");
        cmo.Salary = 260000;
        cmo.Level = 9;
        cmo.HireDate = DateTime.Now.AddYears(-3).AddMonths(-6);
        cmo.Email = "michael.brown@techcorp.com";
        cmo.Phone = "555-345-6789";
        cmo.Location = "New York";
        cmo.Manager = ceo;
        cmo.AddSkill("Marketing Strategy");
        cmo.AddSkill("Brand Management");
        cmo.AddSkill("Digital Marketing");
        
        Employee cfo = new Employee("EMP-004", "Jessica Williams", "CFO", "Finance");
        cfo.Salary = 270000;
        cfo.Level = 9;
        cfo.HireDate = DateTime.Now.AddYears(-3);
        cfo.Email = "jessica.williams@techcorp.com";
        cfo.Phone = "555-456-7890";
        cfo.Location = "New York";
        cfo.Manager = ceo;
        cfo.AddSkill("Financial Management");
        cfo.AddSkill("Budgeting");
        cfo.AddSkill("Investment Management");
        
        Employee hrDirector = new Employee("EMP-005", "David Miller", "HR Director", "Human Resources");
        hrDirector.Salary = 220000;
        hrDirector.Level = 8;
        hrDirector.HireDate = DateTime.Now.AddYears(-2).AddMonths(-8);
        hrDirector.Email = "david.miller@techcorp.com";
        hrDirector.Phone = "555-567-8901";
        hrDirector.Location = "Chicago";
        hrDirector.Manager = ceo;
        hrDirector.AddSkill("HR Management");
        hrDirector.AddSkill("Talent Acquisition");
        hrDirector.AddSkill("Employee Relations");
        
        Employee devManager = new Employee("EMP-006", "Sarah Davis", "Development Manager", "Software Development");
        devManager.Salary = 190000;
        devManager.Level = 7;
        devManager.HireDate = DateTime.Now.AddYears(-3).AddMonths(-2);
        devManager.Email = "sarah.davis@techcorp.com";
        devManager.Phone = "555-678-9012";
        devManager.Location = "San Francisco";
        devManager.Manager = cto;
        devManager.AddSkill("Team Management");
        devManager.AddSkill("Software Development");
        devManager.AddSkill("Agile Methodologies");
        
        Employee qaManager = new Employee("EMP-007", "Robert Wilson", "QA Manager", "QA & Testing");
        qaManager.Salary = 180000;
        qaManager.Level = 7;
        qaManager.HireDate = DateTime.Now.AddYears(-2).AddMonths(-5);
        qaManager.Email = "robert.wilson@techcorp.com";
        qaManager.Phone = "555-789-0123";
        qaManager.Location = "San Francisco";
        qaManager.Manager = cto;
        qaManager.AddSkill("Quality Assurance");
        qaManager.AddSkill("Test Automation");
        qaManager.AddSkill("Team Management");
        
        // 添加更多员工 - 开发团队
        Employee seniorDev1 = new Employee("EMP-008", "Jennifer Lee", "Senior Developer", "Software Development");
        seniorDev1.Salary = 150000;
        seniorDev1.Level = 6;
        seniorDev1.HireDate = DateTime.Now.AddYears(-2);
        seniorDev1.Location = "San Francisco";
        seniorDev1.Manager = devManager;
        seniorDev1.AddSkill("Java");
        seniorDev1.AddSkill("C#");
        seniorDev1.AddSkill("Architecture");
        
        Employee seniorDev2 = new Employee("EMP-009", "Thomas Martin", "Senior Developer", "Software Development");
        seniorDev2.Salary = 145000;
        seniorDev2.Level = 6;
        seniorDev2.HireDate = DateTime.Now.AddYears(-1).AddMonths(-8);
        seniorDev2.Location = "San Francisco";
        seniorDev2.Manager = devManager;
        seniorDev2.AddSkill("JavaScript");
        seniorDev2.AddSkill("React");
        seniorDev2.AddSkill("Node.js");
        
        Employee dev1 = new Employee("EMP-010", "Laura Thompson", "Developer", "Software Development");
        dev1.Salary = 120000;
        dev1.Level = 5;
        dev1.HireDate = DateTime.Now.AddYears(-1);
        dev1.Location = "San Francisco";
        dev1.Manager = devManager;
        dev1.AddSkill("Python");
        dev1.AddSkill("Django");
        
        Employee dev2 = new Employee("EMP-011", "James Anderson", "Developer", "Software Development");
        dev2.Salary = 115000;
        dev2.Level = 5;
        dev2.HireDate = DateTime.Now.AddMonths(-8);
        dev2.Location = "San Francisco";
        dev2.Manager = devManager;
        dev2.AddSkill("C#");
        dev2.AddSkill(".NET Core");
        
        Employee juniorDev = new Employee("EMP-012", "Elizabeth Clark", "Junior Developer", "Software Development");
        juniorDev.Salary = 90000;
        juniorDev.Level = 4;
        juniorDev.HireDate = DateTime.Now.AddMonths(-3);
        juniorDev.Location = "San Francisco";
        juniorDev.Manager = devManager;
        juniorDev.AddSkill("HTML/CSS");
        juniorDev.AddSkill("JavaScript");
        
        // 添加员工到部门
        rootDept.AddEmployee(ceo);
        engineeringDept.AddEmployee(cto);
        marketingDept.AddEmployee(cmo);
        financeDept.AddEmployee(cfo);
        hrDept.AddEmployee(hrDirector);
        softwareDept.AddEmployee(devManager);
        softwareDept.AddEmployee(seniorDev1);
        softwareDept.AddEmployee(seniorDev2);
        softwareDept.AddEmployee(dev1);
        softwareDept.AddEmployee(dev2);
        softwareDept.AddEmployee(juniorDev);
        qaTestingDept.AddEmployee(qaManager);
        
        // 设置部门管理者
        rootDept.Manager = ceo;
        engineeringDept.Manager = cto;
        marketingDept.Manager = cmo;
        financeDept.Manager = cfo;
        hrDept.Manager = hrDirector;
        softwareDept.Manager = devManager;
        qaTestingDept.Manager = qaManager;
        
        // 设置组织的根部门
        organization.SetRootDepartment(rootDept);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078

# 16. 中介者模式

原理:
中介者模式定义一个对象来封装一组对象之间的交互,通过中介者对象来协调各对象之间的通信,从而避免对象之间的直接引用,降低耦合。

思路:

  1. 定义中介者接口,声明与各个组件通信的方法
  2. 实现具体中介者类,协调组件之间的交互
  3. 定义组件接口,声明与中介者交互的方法
  4. 实现具体组件类,它们通过中介者与其他组件通信

前辈经验:

  • 当对象之间的交互复杂,形成网状结构时,使用中介者模式
  • 中介者模式将多对多的交互转变为一对多,降低组件间的耦合
  • 中介者可能会成为性能瓶颈或过于复杂,需要合理设计
  • 对于简单的对象交互,不需要使用中介者模式
  • 中介者模式常用于图形用户界面的开发中

业务场景:
航空交通管制系统,飞机不直接通信,而是通过控制塔台协调。

简单实现:

// 中介者接口
public interface IAirTrafficControl
{
    void RegisterAircraft(Aircraft aircraft);
    void SendMessage(string from, string message);
    void RequestLanding(Aircraft aircraft);
    void RequestTakeOff(Aircraft aircraft);
}

// 具体中介者 - 控制塔台
public class ControlTower : IAirTrafficControl
{
    private readonly Dictionary<string, Aircraft> _registeredAircraft = new Dictionary<string, Aircraft>();
    private readonly Queue<Aircraft> _landingQueue = new Queue<Aircraft>();
    private readonly Queue<Aircraft> _takeOffQueue = new Queue<Aircraft>();
    private bool _runwayFree = true;
    
    public void RegisterAircraft(Aircraft aircraft)
    {
        if (!_registeredAircraft.ContainsKey(aircraft.CallSign))
        {
            _registeredAircraft[aircraft.CallSign] = aircraft;
            SendMessage("Control Tower", $"Aircraft {aircraft.CallSign} registered with the tower.");
        }
    }
    
    public void SendMessage(string from, string message)
    {
        Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {from}: {message}");
    }
    
    public void RequestLanding(Aircraft aircraft)
    {
        SendMessage(aircraft.CallSign, "Requesting permission to land.");
        
        if (_runwayFree)
        {
            _runwayFree = false;
            SendMessage("Control Tower", $"{aircraft.CallSign} cleared for landing.");
            
            // 模拟飞机降落
            Task.Run(async () =>
            {
                await Task.Delay(3000); // 降落需要3秒
                aircraft.Land();
                _runwayFree = true;
                
                // 检查是否有其他飞机在等待
                ProcessNextOperation();
            });
        }
        else
        {
            SendMessage("Control Tower", $"{aircraft.CallSign} please hold, runway occupied. Added to landing queue.");
            _landingQueue.Enqueue(aircraft);
        }
    }
    
    public void RequestTakeOff(Aircraft aircraft)
    {
        SendMessage(aircraft.CallSign, "Requesting permission to take off.");
        
        if (_runwayFree)
        {
            _runwayFree = false;
            SendMessage("Control Tower", $"{aircraft.CallSign} cleared for take-off.");
            
            // 模拟飞机起飞
            Task.Run(async () =>
            {
                await Task.Delay(2000); // 起飞需要2秒
                aircraft.TakeOff();
                _runwayFree = true;
                
                // 检查是否有其他飞机在等待
                ProcessNextOperation();
            });
        }
        else
        {
            SendMessage("Control Tower", $"{aircraft.CallSign} please wait, runway occupied. Added to take-off queue.");
            _takeOffQueue.Enqueue(aircraft);
        }
    }
    
    private void ProcessNextOperation()
    {
        if (_landingQueue.Count > 0)
        {
            // 优先处理降落请求
            Aircraft aircraft = _landingQueue.Dequeue();
            SendMessage("Control Tower", $"{aircraft.CallSign} now cleared for landing.");
            
            _runwayFree = false;
            Task.Run(async () =>
            {
                await Task.Delay(3000); // 降落需要3秒
                aircraft.Land();
                _runwayFree = true;
                
                ProcessNextOperation();
            });
        }
        else if (_takeOffQueue.Count > 0)
        {
            // 然后处理起飞请求
            Aircraft aircraft = _takeOffQueue.Dequeue();
            SendMessage("Control Tower", $"{aircraft.CallSign} now cleared for take-off.");
            
            _runwayFree = false;
            Task.Run(async () =>
            {
                await Task.Delay(2000); // 起飞需要2秒
                aircraft.TakeOff();
                _runwayFree = true;
                
                ProcessNextOperation();
            });
        }
    }
}

// 组件类 - 飞机
public class Aircraft
{
    private readonly IAirTrafficControl _atc;
    private bool _isInAir;
    
    public string CallSign { get; }
    public string Model { get; }
    
    public Aircraft(string callSign, string model, IAirTrafficControl atc)
    {
        CallSign = callSign;
        Model = model;
        _atc = atc;
        _isInAir = false;
        
        // 注册到控制塔台
        _atc.RegisterAircraft(this);
    }
    
    public void RequestLanding()
    {
        if (_isInAir)
        {
            _atc.RequestLanding(this);
        }
        else
        {
            _atc.SendMessage(CallSign, "Cannot request landing, aircraft is on the ground.");
        }
    }
    
    public void RequestTakeOff()
    {
        if (!_isInAir)
        {
            _atc.RequestTakeOff(this);
        }
        else
        {
            _atc.SendMessage(CallSign, "Cannot request take-off, aircraft is already in the air.");
        }
    }
    
    public void SendMessage(string message)
    {
        _atc.SendMessage(CallSign, message);
    }
    
    public void Land()
    {
        _isInAir = false;
        _atc.SendMessage(CallSign, "Landing completed.");
    }
    
    public void TakeOff()
    {
        _isInAir = true;
        _atc.SendMessage(CallSign, "Take-off completed.");
    }
    
    public void SetFlyingStatus(bool isInAir)
    {
        _isInAir = isInAir;
    }
}

// 客户端代码
public class Client
{
    public static async Task Main()
    {
        // 创建中介者 - 控制塔台
        IAirTrafficControl controlTower = new ControlTower();
        
        // 创建飞机
        Aircraft flight1 = new Aircraft("BA287", "Boeing 777", controlTower);
        Aircraft flight2 = new Aircraft("LH492", "Airbus A380", controlTower);
        Aircraft flight3 = new Aircraft("SQ321", "Boeing 787", controlTower);
        
        // 设置初始状态
        flight1.SetFlyingStatus(true);  // 空中
        flight2.SetFlyingStatus(false); // 地面
        flight3.SetFlyingStatus(true);  // 空中
        
        // 模拟空中交通
        flight1.SendMessage("Approaching airport, 30 miles out.");
        await Task.Delay(1000);
        
        flight2.SendMessage("Ready for departure.");
        await Task.Delay(1000);
        
        flight3.SendMessage("Circling at 10,000 feet.");
        await Task.Delay(1000);
        
        // 请求降落和起飞
        flight1.RequestLanding();
        await Task.Delay(1000);
        
        flight2.RequestTakeOff();
        await Task.Delay(1000);
        
        flight3.RequestLanding();
        await Task.Delay(10000); // 等待所有操作完成
        
        // 再次请求操作
        flight2.RequestLanding();
        
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

复杂实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

// 1. 中介者接口
public interface IAirTrafficControl
{
    void RegisterAircraft(IAircraft aircraft);
    void DeregisterAircraft(IAircraft aircraft);
    void SendMessage(string from, string message, MessageType type = MessageType.Information);
    void SendDirectMessage(string from, string to, string message);
    Task<bool> RequestLanding(IAircraft aircraft, int runwayPreference = -1);
    Task<bool> RequestTakeOff(IAircraft aircraft, int runwayPreference = -1);
    Task<bool> RequestEmergencyLanding(IAircraft aircraft);
    void ReportPosition(IAircraft aircraft, Position position);
    void ReportStatus(IAircraft aircraft, AircraftStatus status);
    Task<GateAssignment> RequestGate(IAircraft aircraft);
    void ReleaseGate(IAircraft aircraft, string gateNumber);
    WeatherInfo GetCurrentWeather();
    int GetQueuePosition(IAircraft aircraft, OperationType operationType);
    IReadOnlyList<IAircraft> GetRegisteredAircraft();
    void AddObserver(IAirTrafficObserver observer);
    void RemoveObserver(IAirTrafficObserver observer);
}

// 2. 消息类型枚举
public enum MessageType
{
    Information,
    Warning,
    Emergency,
    ControllerCommand,
    SystemAlert,
    Weather
}

// 3. 操作类型枚举
public enum OperationType
{
    Landing,
    TakeOff
}

// 4. 位置类
public class Position
{
    public double Latitude { get; set; }
    public double Longitude { get; set; }
    public double Altitude { get; set; }
    public double Heading { get; set; }
    public double Speed { get; set; }
    
    public Position(double latitude, double longitude, double altitude, double heading, double speed)
    {
        Latitude = latitude;
        Longitude = longitude;
        Altitude = altitude;
        Heading = heading;
        Speed = speed;
    }
    
    // 计算两个位置之间的距离(简化版本)
    public double DistanceTo(Position other)
    {
        // 使用简单的欧氏距离计算,实际应用中应使用大圆距离
        double latDiff = Latitude - other.Latitude;
        double longDiff = Longitude - other.Longitude;
        return Math.Sqrt(latDiff * latDiff + longDiff * longDiff) * 60; // 近似转换为海里
    }
    
    public override string ToString()
    {
        return $"({Latitude:F2}, {Longitude:F2}) at {Altitude:F0} ft, heading {Heading:F0}°, speed {Speed:F0} knots";
    }
}

// 5. 天气信息类
public class WeatherInfo
{
    public double WindSpeed { get; set; }
    public double WindDirection { get; set; }
    public double Visibility { get; set; }
    public double Temperature { get; set; }
    public string Conditions { get; set; }
    public bool IsSevere { get; set; }
    public DateTime Timestamp { get; set; }
    
    public WeatherInfo()
    {
        Timestamp = DateTime.Now;
    }
    
    public override string ToString()
    {
        return $"{Conditions}, Wind: {WindSpeed:F1} knots at {WindDirection:F0}°, Visibility: {Visibility:F1} miles, Temp: {Temperature:F1}°C";
    }
}

// 6. 飞机状态枚举
public enum AircraftStatus
{
    Parked,
    Taxiing,
    ReadyForTakeOff,
    TakingOff,
    Airborne,
    Approaching,
    OnFinalApproach,
    Landing,
    EmergencyOperation,
    Diverted
}

// 7. 飞机类型枚举
public enum AircraftType
{
    SmallPrivate,
    MediumCommercial,
    LargeCommercial,
    Cargo,
    Military
}

// 8. 登机口分配类
public class GateAssignment
{
    public string GateNumber { get; set; }
    public string Terminal { get; set; }
    public DateTime AssignedTime { get; set; }
    public DateTime ExpiryTime { get; set; }
    
    public GateAssignment(string gateNumber, string terminal)
    {
        GateNumber = gateNumber;
        Terminal = terminal;
        AssignedTime = DateTime.Now;
        ExpiryTime = AssignedTime.AddHours(2); // 默认2小时
    }
    
    public override string ToString()
    {
        return $"Gate {GateNumber} at Terminal {Terminal}, assigned until {ExpiryTime:HH:mm}";
    }
}

// 9. 跑道类
public class Runway
{
    public int RunwayNumber { get; }
    public string Designation { get; }
    public double Length { get; }
    public bool IsOperational { get; set; }
    public bool IsOccupied { get; private set; }
    public IAircraft CurrentAircraft { get; private set; }
    
    // 适合的飞机类型
    public HashSet<AircraftType> SuitableFor { get; } = new HashSet<AircraftType>();
    
    public Runway(int runwayNumber, string designation, double length)
    {
        RunwayNumber = runwayNumber;
        Designation = designation;
        Length = length;
        IsOperational = true;
        IsOccupied = false;
    }
    
    public bool CanAccept(AircraftType aircraftType)
    {
        return IsOperational && SuitableFor.Contains(aircraftType);
    }
    
    public void SetOccupied(IAircraft aircraft)
    {
        IsOccupied = true;
        CurrentAircraft = aircraft;
    }
    
    public void SetFree()
    {
        IsOccupied = false;
        CurrentAircraft = null;
    }
    
    public override string ToString()
    {
        return $"Runway {Designation} ({Length:F0} ft) - {(IsOperational ? "Operational" : "Closed")}, {(IsOccupied ? "Occupied" : "Free")}";
    }
}

// 10. 机场观察者接口
public interface IAirTrafficObserver
{
    void Update(string message, MessageType messageType);
    void UpdateAircraftStatus(IAircraft aircraft, AircraftStatus oldStatus, AircraftStatus newStatus);
    void UpdateRunwayStatus(Runway runway, bool wasOccupied, bool isOccupied);
    void UpdateWeather(WeatherInfo weatherInfo);
}

// 11. 飞机接口
public interface IAircraft
{
    string CallSign { get; }
    string Model { get; }
    AircraftType Type { get; }
    AircraftStatus Status { get; }
    Position CurrentPosition { get; }
    double FuelRemaining { get; } // 以分钟为单位
    bool HasEmergency { get; }
    string CurrentGate { get; }
    
    void SetStatus(AircraftStatus status);
    void SetPosition(Position position);
    Task Land(int runwayNumber);
    Task TakeOff(int runwayNumber);
    Task EmergencyLand(int runwayNumber);
    void AssignGate(GateAssignment gate);
    void DeclareEmergency(string reason);
    void ResolveEmergency();
    void SendMessage(string message);
    void ReceiveMessage(string from, string message, MessageType type);
}

// 12. 具体中介者 - 高级控制塔台
public class AdvancedControlTower : IAirTrafficControl
{
    private readonly Dictionary<string, IAircraft> _registeredAircraft = new Dictionary<string, IAircraft>();
    private readonly List<Runway> _runways = new List<Runway>();
    private readonly Dictionary<string, GateAssignment> _gates = new Dictionary<string, GateAssignment>();
    private readonly Queue<IAircraft> _landingQueue = new Queue<IAircraft>();
    private readonly Queue<IAircraft> _takeOffQueue = new Queue<IAircraft>();
    private readonly Queue<IAircraft> _emergencyQueue = new Queue<IAircraft>();
    private readonly Dictionary<string, HashSet<string>> _occupiedGates = new Dictionary<string, HashSet<string>>();
    private readonly Dictionary<string, string> _aircraftGateAssignments = new Dictionary<string, string>();
    private readonly List<IAirTrafficObserver> _observers = new List<IAirTrafficObserver>();
    private WeatherInfo _currentWeather = new WeatherInfo
    {
        WindSpeed = 5,
        WindDirection = 270,
        Visibility = 10,
        Temperature = 22,
        Conditions = "Clear",
        IsSevere = false
    };
    
    private readonly Random _random = new Random();
    private readonly SemaphoreSlim _runwayLock = new SemaphoreSlim(1, 1);
    private readonly SemaphoreSlim _gateLock = new SemaphoreSlim(1, 1);
    
    public AdvancedControlTower()
    {
        InitializeRunways();
        InitializeGates();
        
        // 启动天气更新线程
        Task.Run(WeatherUpdateLoop);
        
        // 启动状态监控线程
        Task.Run(StatusMonitorLoop);
    }
    
    private void InitializeRunways()
    {
        // 创建跑道
        var runway1 = new Runway(1, "09L/27R", 11000);
        runway1.SuitableFor.Add(AircraftType.SmallPrivate);
        runway1.SuitableFor.Add(AircraftType.MediumCommercial);
        runway1.SuitableFor.Add(AircraftType.LargeCommercial);
        runway1.SuitableFor.Add(AircraftType.Cargo);
        runway1.SuitableFor.Add(AircraftType.Military);
        
        var runway2 = new Runway(2, "09R/27L", 9000);
        runway2.SuitableFor.Add(AircraftType.SmallPrivate);
        runway2.SuitableFor.Add(AircraftType.MediumCommercial);
        runway2.SuitableFor.Add(AircraftType.Cargo);
        
        var runway3 = new Runway(3, "14/32", 7500);
        runway3.SuitableFor.Add(AircraftType.SmallPrivate);
        runway3.SuitableFor.Add(AircraftType.MediumCommercial);
        
        _runways.Add(runway1);
        _runways.Add(runway2);
        _runways.Add(runway3);
    }
    
    private void InitializeGates()
    {
        // 初始化航站楼和登机口
        string[] terminals = { "A", "B", "C" };
        
        foreach (var terminal in terminals)
        {
            _occupiedGates[terminal] = new HashSet<string>();
            
            // 每个航站楼10个登机口
            for (int i = 1; i <= 10; i++)
            {
                string gateNumber = $"{terminal}{i}";
                _gates[gateNumber] = new GateAssignment(gateNumber, terminal);
            }
        }
    }
    
    public void RegisterAircraft(IAircraft aircraft)
    {
        if (!_registeredAircraft.ContainsKey(aircraft.CallSign))
        {
            _registeredAircraft[aircraft.CallSign] = aircraft;
            SendMessage("Control Tower", $"Aircraft {aircraft.CallSign} ({aircraft.Model}) registered with the tower.");
            
            foreach (var observer in _observers)
            {
                observer.Update($"Aircraft {aircraft.CallSign} registered", MessageType.Information);
            }
        }
    }
    
    public void DeregisterAircraft(IAircraft aircraft)
    {
        if (_registeredAircraft.ContainsKey(aircraft.CallSign))
        {
            _registeredAircraft.Remove(aircraft.CallSign);
            
            // 如果飞机在队列中,移除它
            _landingQueue = new Queue<IAircraft>(_landingQueue.Where(a => a.CallSign != aircraft.CallSign));
            _takeOffQueue = new Queue<IAircraft>(_takeOffQueue.Where(a => a.CallSign != aircraft.CallSign));
            
            // 释放登机口
            if (_aircraftGateAssignments.ContainsKey(aircraft.CallSign))
            {
                string gateNumber = _aircraftGateAssignments[aircraft.CallSign];
                ReleaseGate(aircraft, gateNumber);
            }
            
            SendMessage("Control Tower", $"Aircraft {aircraft.CallSign} deregistered from the tower.");
            
            foreach (var observer in _observers)
            {
                observer.Update($"Aircraft {aircraft.CallSign} deregistered", MessageType.Information);
            }
        }
    }
    
    public void SendMessage(string from, string message, MessageType type = MessageType.Information)
    {
        string formattedMessage = $"[{DateTime.Now:HH:mm:ss}] {from}: {message}";
        
        // 根据消息类型添加前缀
        switch (type)
        {
            case MessageType.Warning:
                formattedMessage = "⚠️ " + formattedMessage;
                break;
            case MessageType.Emergency:
                formattedMessage = "🚨 " + formattedMessage;
                break;
            case MessageType.ControllerCommand:
                formattedMessage = "👮 " + formattedMessage;
                break;
            case MessageType.SystemAlert:
                formattedMessage = "🔔 " + formattedMessage;
                break;
            case MessageType.Weather:
                formattedMessage = "☁️ " + formattedMessage;
                break;
        }
        
        Console.WriteLine(formattedMessage);
        
        // 通知所有观察者
        foreach (var observer in _observers)
        {
            observer.Update($"{from}: {message}", type);
        }
    }
    
    public void SendDirectMessage(string from, string to, string message)
    {
        if (_registeredAircraft.TryGetValue(to, out IAircraft recipient))
        {
            recipient.ReceiveMessage(from, message, MessageType.Information);
            
            // 记录直接消息
            SendMessage("System", $"Direct message from {from} to {to}", MessageType.Information);
        }
        else
        {
            SendMessage("System", $"Cannot send message to {to}: Aircraft not found", MessageType.Warning);
        }
    }
    
    public async Task<bool> RequestLanding(IAircraft aircraft, int runwayPreference = -1)
    {
        SendMessage(aircraft.CallSign, "Requesting permission to land.", MessageType.Information);
        
        // 如果有紧急情况,拒绝常规降落请求
        if (aircraft.HasEmergency)
        {
            SendMessage("Control Tower", $"{aircraft.CallSign} you have declared an emergency, please use emergency protocol.", MessageType.ControllerCommand);
            return false;
        }
        
        // 检查天气条件
        if (_currentWeather.IsSevere)
        {
            SendMessage("Control Tower", $"{aircraft.CallSign} landing operations currently restricted due to severe weather: {_currentWeather.Conditions}.", MessageType.Weather);
            return false;
        }
        
        await _runwayLock.WaitAsync();
        try
        {
            // 尝试找到合适的跑道
            Runway selectedRunway = null;
            
            if (runwayPreference >= 0 && runwayPreference < _runways.Count)
            {
                // 检查首选跑道是否可用
                var preferredRunway = _runways[runwayPreference];
                if (!preferredRunway.IsOccupied && preferredRunway.IsOperational && preferredRunway.CanAccept(aircraft.Type))
                {
                    selectedRunway = preferredRunway;
                }
            }
            
            // 如果首选跑道不可用,尝试找到其他可用跑道
            if (selectedRunway == null)
            {
                selectedRunway = _runways.FirstOrDefault(r => !r.IsOccupied && r.IsOperational && r.CanAccept(aircraft.Type));
            }
            
            if (selectedRunway != null)
            {
                selectedRunway.SetOccupied(aircraft);
                
                // 通知观察者跑道状态变化
                foreach (var observer in _observers)
                {
                    observer.UpdateRunwayStatus(selectedRunway, false, true);
                }
                
                SendMessage("Control Tower", $"{aircraft.CallSign} cleared for landing on Runway {selectedRunway.Designation}.", MessageType.ControllerCommand);
                
                // 异步处理降落
                Task.Run(async () =>
                {
                    try
                    {
                        await aircraft.Land(selectedRunway.RunwayNumber);
                    }
                    finally
                    {
                        await _runwayLock.WaitAsync();
                        try
                        {
                            // 降落完成后释放跑道
                            selectedRunway.SetFree();
                            
                            // 通知观察者跑道状态变化
                            foreach (var observer in _observers)
                            {
                                observer.UpdateRunwayStatus(selectedRunway, true, false);
                            }
                            
                            // 处理下一个等待的飞机
                            await ProcessNextAircraftAsync();
                        }
                        finally
                        {
                            _runwayLock.Release();
                        }
                    }
                });
                
                return true;
            }
            else
            {
                // 所有跑道都忙,加入等待队列
                _landingQueue.Enqueue(aircraft);
                int queuePosition = _landingQueue.Count;
                
                SendMessage("Control Tower", $"{aircraft.CallSign} please hold, all suitable runways occupied. Added to landing queue at position {queuePosition}.", MessageType.ControllerCommand);
                return false;
            }
        }
        finally
        {
            _runwayLock.Release();
        }
    }
    
    public async Task<bool> RequestTakeOff(IAircraft aircraft, int runwayPreference = -1)
    {
        SendMessage(aircraft.CallSign, "Requesting permission to take off.", MessageType.Information);
        
        // 检查天气条件
        if (_currentWeather.IsSevere)
        {
            SendMessage("Control Tower", $"{aircraft.CallSign} take-off operations currently restricted due to severe weather: {_currentWeather.Conditions}.", MessageType.Weather);
            return false;
        }
        
        await _runwayLock.WaitAsync();
        try
        {
            // 尝试找到合适的跑道
            Runway selectedRunway = null;
            
            if (runwayPreference >= 0 && runwayPreference < _runways.Count)
            {
                // 检查首选跑道是否可用
                var preferredRunway = _runways[runwayPreference];
                if (!preferredRunway.IsOccupied && preferredRunway.IsOperational && preferredRunway.CanAccept(aircraft.Type))
                {
                    selectedRunway = preferredRunway;
                }
            }
            
            // 如果首选跑道不可用,尝试找到其他可用跑道
            if (selectedRunway == null)
            {
                selectedRunway = _runways.FirstOrDefault(r => !r.IsOccupied && r.IsOperational && r.CanAccept(aircraft.Type));
            }
            
            if (selectedRunway != null)
            {
                selectedRunway.SetOccupied(aircraft);
                
                // 通知观察者跑道状态变化
                foreach (var observer in _observers)
                {
                    observer.UpdateRunwayStatus(selectedRunway, false, true);
                }
                
                SendMessage("Control Tower", $"{aircraft.CallSign} cleared for take-off on Runway {selectedRunway.Designation}.", MessageType.ControllerCommand);
                
                // 异步处理起飞
                Task.Run(async () =>
                {
                    try
                    {
                        // 如果飞机有分配的登机口,释放它
                        if (_aircraftGateAssignments.ContainsKey(aircraft.CallSign))
                        {
                            string gateNumber = _aircraftGateAssignments[aircraft.CallSign];
                            ReleaseGate(aircraft, gateNumber);
                        }
                        
                        await aircraft.TakeOff(selectedRunway.RunwayNumber);
                    }
                    finally
                    {
                        await _runwayLock.WaitAsync();
                        try
                        {
                            // 起飞完成后释放跑道
                            selectedRunway.SetFree();
                            
                            // 通知观察者跑道状态变化
                            foreach (var observer in _observers)
                            {
                                observer.UpdateRunwayStatus(selectedRunway, true, false);
                            }
                            
                            // 处理下一个等待的飞机
                            await ProcessNextAircraftAsync();
                        }
                        finally
                        {
                            _runwayLock.Release();
                        }
                    }
                });
                
                return true;
            }
            else
            {
                // 所有跑道都忙,加入等待队列
                _takeOffQueue.Enqueue(aircraft);
                int queuePosition = _takeOffQueue.Count;
                
                SendMessage("Control Tower", $"{aircraft.CallSign} please wait, all suitable runways occupied. Added to take-off queue at position {queuePosition}.", MessageType.ControllerCommand);
                return false;
            }
        }
        finally
        {
            _runwayLock.Release();
        }
    }
    
    public async Task<bool> RequestEmergencyLanding(IAircraft aircraft)
    {
        SendMessage(aircraft.CallSign, "DECLARING EMERGENCY! Requesting immediate landing clearance.", MessageType.Emergency);
        
        await _runwayLock.WaitAsync();
        try
        {
            // 紧急情况优先处理,尝试找到合适的跑道
            Runway selectedRunway = _runways.FirstOrDefault(r => !r.IsOccupied && r.IsOperational && r.CanAccept(aircraft.Type));
            
            if (selectedRunway != null)
            {
                selectedRunway.SetOccupied(aircraft);
                
                // 通知观察者跑道状态变化
                foreach (var observer in _observers)
                {
                    observer.UpdateRunwayStatus(selectedRunway, false, true);
                }
                
                SendMessage("Control Tower", $"EMERGENCY AIRCRAFT {aircraft.CallSign} CLEARED FOR IMMEDIATE LANDING on Runway {selectedRunway.Designation}. All other aircraft hold positions.", MessageType.Emergency);
                
                // 广播给所有飞机
                foreach (var otherAircraft in _registeredAircraft.Values)
                {
                    if (otherAircraft.CallSign != aircraft.CallSign)
                    {
                        otherAircraft.ReceiveMessage("Control Tower", $"EMERGENCY IN PROGRESS. Aircraft {aircraft.CallSign} performing emergency landing on Runway {selectedRunway.Designation}. Maintain holding pattern.", MessageType.Emergency);
                    }
                }
                
                // 异步处理紧急降落
                Task.Run(async () =>
                {
                    try
                    {
                        await aircraft.EmergencyLand(selectedRunway.RunwayNumber);
                    }
                    finally
                    {
                        await _runwayLock.WaitAsync();
                        try
                        {
                            // 降落完成后释放跑道
                            selectedRunway.SetFree();
                            
                            // 通知观察者跑道状态变化
                            foreach (var observer in _observers)
                            {
                                observer.UpdateRunwayStatus(selectedRunway, true, false);
                            }
                            
                            SendMessage("Control Tower", $"Emergency landing of {aircraft.CallSign} completed. Resuming normal operations.", MessageType.ControllerCommand);
                            
                            // 处理下一个等待的飞机
                            await ProcessNextAircraftAsync();
                        }
                        finally
                        {
                            _runwayLock.Release();
                        }
                    }
                });
                
                return true;
            }
            else
            {
                // 所有跑道都忙,需要安排一个跑道
                var busyRunway = _runways.FirstOrDefault(r => r.IsOperational && r.CanAccept(aircraft.Type));
                
                if (busyRunway != null)
                {
                    // 将正在使用跑道的飞机中断操作
                    IAircraft currentAircraft = busyRunway.CurrentAircraft;
                    
                    if (currentAircraft != null)
                    {
                        SendMessage("Control Tower", $"EMERGENCY OVERRIDE: {currentAircraft.CallSign} abort operation and clear Runway {busyRunway.Designation} immediately for emergency landing.", MessageType.Emergency);
                        
                        currentAircraft.ReceiveMessage("Control Tower", $"ABORT OPERATION IMMEDIATELY. Aircraft {aircraft.CallSign} requires emergency landing. Clear runway and enter holding pattern.", MessageType.Emergency);
                    }
                    
                    busyRunway.SetOccupied(aircraft);
                    
                    // 通知观察者跑道状态变化
                    foreach (var observer in _observers)
                    {
                        observer.UpdateRunwayStatus(busyRunway, true, true);
                    }
                    
                    SendMessage("Control Tower", $"EMERGENCY AIRCRAFT {aircraft.CallSign} CLEARED FOR IMMEDIATE LANDING on Runway {busyRunway.Designation}. All other aircraft hold positions.", MessageType.Emergency);
                    
                    // 异步处理紧急降落
                    Task.Run(async () =>
                    {
                        try
                        {
                            await aircraft.EmergencyLand(busyRunway.RunwayNumber);
                        }
                        finally
                        {
                            await _runwayLock.WaitAsync();
                            try
                            {
                                // 降落完成后释放跑道
                                busyRunway.SetFree();
                                
                                // 通知观察者跑道状态变化
                                foreach (var observer in _observers)
                                {
                                    observer.UpdateRunwayStatus(busyRunway, true, false);
                                }
                                
                                SendMessage("Control Tower", $"Emergency landing of {aircraft.CallSign} completed. Resuming normal operations.", MessageType.ControllerCommand);
                                
                                // 处理下一个等待的飞机
                                await ProcessNextAircraftAsync();
                            }
                            finally
                            {
                                _runwayLock.Release();
                            }
                        }
                    });
                    
                    return true;
                }
                else
                {
                    // 极端情况:没有适合的跑道
                    SendMessage("Control Tower", $"CRITICAL SITUATION: No suitable runway available for {aircraft.CallSign}. Diverting to alternate airport.", MessageType.Emergency);
                    aircraft.ReceiveMessage("Control Tower", "No suitable runway available. Divert to alternate airport immediately.", MessageType.Emergency);
                    return false;
                }
            }
        }
        finally
        {
            _runwayLock.Release();
        }
    }
    
    private async Task ProcessNextAircraftAsync()
    {
        // 优先处理紧急情况
        if (_emergencyQueue.Count > 0)
        {
            IAircraft aircraft = _emergencyQueue.Dequeue();
            await RequestEmergencyLanding(aircraft);
            return;
        }
        
        // 然后处理降落(通常降落优先于起飞)
        if (_landingQueue.Count > 0)
        {
            IAircraft aircraft = _landingQueue.Dequeue();
            await RequestLanding(aircraft);
            return;
        }
        
        // 最后处理起飞
        if (_takeOffQueue.Count > 0)
        {
            IAircraft aircraft = _takeOffQueue.Dequeue();
            await RequestTakeOff(aircraft);
        }
    }
    
    public void ReportPosition(IAircraft aircraft, Position position)
    {
        // 更新飞机位置
        aircraft.SetPosition(position);
        
        // 机场附近的飞机会收到更频繁的位置报告
        // 这里简化为每10次位置报告记录一次
        if (_random.Next(10) == 0)
        {
            SendMessage(aircraft.CallSign, $"Position: {position}", MessageType.Information);
        }
        
        // 检查飞机是否接近机场
        if (aircraft.Status == AircraftStatus.Airborne && 
            position.Altitude < 10000 && 
            IsNearAirport(position))
        {
            // 提醒飞机需要联系塔台请求降落
            if (aircraft.Status != AircraftStatus.Approaching && 
                aircraft.Status != AircraftStatus.OnFinalApproach)
            {
                SendMessage("Control Tower", $"{aircraft.CallSign} you are approaching the airport. Contact tower for landing instructions.", MessageType.ControllerCommand);
            }
        }
    }
    
    private bool IsNearAirport(Position position)
    {
        // 简化:检查飞机是否在机场30海里范围内
        // 实际应用中应使用机场的实际坐标
        Position airportPosition = new Position(0, 0, 0, 0, 0);
        return position.DistanceTo(airportPosition) < 30;
    }
    
    public void ReportStatus(IAircraft aircraft, AircraftStatus status)
    {
        AircraftStatus oldStatus = aircraft.Status;
        
        // 更新飞机状态
        aircraft.SetStatus(status);
        
        // 记录状态变更
        SendMessage(aircraft.CallSign, $"Status changed from {oldStatus} to {status}", MessageType.Information);
        
        // 通知观察者状态变化
        foreach (var observer in _observers)
        {
            observer.UpdateAircraftStatus(aircraft, oldStatus, status);
        }
        
        // 根据新状态执行相应操作
        switch (status)
        {
            case AircraftStatus.Parked:
                if (string.IsNullOrEmpty(aircraft.CurrentGate))
                {
                    // 如果飞机已降落但没有登机口,请求分配
                    Task.Run(async () => 
                    {
                        var gate = await RequestGate(aircraft);
                        if (gate != null)
                        {
                            aircraft.AssignGate(gate);
                        }
                    });
                }
                break;
                
            case AircraftStatus.ReadyForTakeOff:
                // 飞机准备起飞,加入起飞队列
                if (!_takeOffQueue.Contains(aircraft))
                {
                    Task.Run(async () => await RequestTakeOff(aircraft));
                }
                break;
                
            case AircraftStatus.Approaching:
                // 飞机正在接近,准备降落
                if (!_landingQueue.Contains(aircraft))
                {
                    Task.Run(async () => await RequestLanding(aircraft));
                }
                break;
                
            case AircraftStatus.EmergencyOperation:
                // 处理紧急情况
                if (!_emergencyQueue.Contains(aircraft))
                {
                    _emergencyQueue.Enqueue(aircraft);
                    Task.Run(async () => await RequestEmergencyLanding(aircraft));
                }
                break;
        }
    }
    
    public async Task<GateAssignment> RequestGate(IAircraft aircraft)
    {
        SendMessage(aircraft.CallSign, "Requesting gate assignment.", MessageType.Information);
        
        await _gateLock.WaitAsync();
        try
        {
            // 根据飞机类型选择合适的航站楼
            string preferredTerminal;
            
            switch (aircraft.Type)
            {
                case AircraftType.LargeCommercial:
                    preferredTerminal = "A";
                    break;
                case AircraftType.MediumCommercial:
                    preferredTerminal = "B";
                    break;
                case AircraftType.SmallPrivate:
                    preferredTerminal = "C";
                    break;
                case AircraftType.Cargo:
                    preferredTerminal = "C";
                    break;
                case AircraftType.Military:
                    preferredTerminal = "C";
                    break;
                default:
                    preferredTerminal = "B";
                    break;
            }
            
            // 尝试找到首选航站楼中的可用登机口
            string assignedGate = null;
            
            // 首先尝试首选航站楼
            foreach (var gate in _gates.Keys.Where(g => g.StartsWith(preferredTerminal)))
            {
                if (!_occupiedGates[preferredTerminal].Contains(gate))
                {
                    assignedGate = gate;
                    break;
                }
            }
            
            // 如果首选航站楼没有可用登机口,尝试其他航站楼
            if (assignedGate == null)
            {
                foreach (var terminal in _occupiedGates.Keys)
                {
                    if (terminal == preferredTerminal) continue;
                    
                    foreach (var gate in _gates.Keys.Where(g => g.StartsWith(terminal)))
                    {
                        if (!_occupiedGates[terminal].Contains(gate))
                        {
                            assignedGate = gate;
                            break;
                        }
                    }
                    
                    if (assignedGate != null) break;
                }
            }
            
            if (assignedGate != null)
            {
                // 分配登机口
                GateAssignment assignment = _gates[assignedGate];
                _occupiedGates[assignment.Terminal].Add(assignedGate);
                _aircraftGateAssignments[aircraft.CallSign] = assignedGate;
                
                SendMessage("Control Tower", $"{aircraft.CallSign} assigned to {assignment.Terminal}-{assignedGate} until {assignment.ExpiryTime:HH:mm}.", MessageType.ControllerCommand);
                return assignment;
            }
            else
            {
                // 所有登机口都已占用
                SendMessage("Control Tower", $"{aircraft.CallSign} no gates available at this time. Hold at current position.", MessageType.ControllerCommand);
                return null;
            }
        }
        finally
        {
            _gateLock.Release();
        }
    }
    
    public void ReleaseGate(IAircraft aircraft, string gateNumber)
    {
        if (string.IsNullOrEmpty(gateNumber)) return;
        
        _gateLock.Wait();
        try
        {
            if (_gates.TryGetValue(gateNumber, out GateAssignment assignment))
            {
                _occupiedGates[assignment.Terminal].Remove(gateNumber);
                _aircraftGateAssignments.Remove(aircraft.CallSign);
                
                SendMessage("Control Tower", $"{aircraft.CallSign} released gate {gateNumber}.", MessageType.Information);
            }
        }
        finally
        {
            _gateLock.Release();
        }
    }
    
    public WeatherInfo GetCurrentWeather()
    {
        return _currentWeather;
    }
    
    private async Task WeatherUpdateLoop()
    {
        while (true)
        {
            await Task.Delay(TimeSpan.FromMinutes(1)); // 每分钟更新一次
            
            // 生成新的天气状况
            UpdateWeather();
            
            // 通知所有飞机新的天气情况
            string weatherMessage = $"Weather update: {_currentWeather}";
            
            if (_currentWeather.IsSevere)
            {
                SendMessage("Weather Station", weatherMessage, MessageType.Weather);
                SendMessage("Control Tower", "ATTENTION ALL AIRCRAFT: Severe weather conditions. Exercise caution.", MessageType.Warning);
                
                foreach (var aircraft in _registeredAircraft.Values)
                {
                    aircraft.ReceiveMessage("Control Tower", weatherMessage, MessageType.Weather);
                }
            }
            else if (_random.Next(5) == 0) // 20%的概率发送普通天气更新
            {
                SendMessage("Weather Station", weatherMessage, MessageType.Weather);
            }
            
            // 通知观察者
            foreach (var observer in _observers)
            {
                observer.UpdateWeather(_currentWeather);
            }
            
            // 检查是否需要关闭跑道
            CheckRunwayStatus();
        }
    }
    
    private void UpdateWeather()
    {
        // 模拟天气变化
        double windChange = (_random.NextDouble() - 0.5) * 5; // -2.5到2.5的风速变化
        double directionChange = (_random.NextDouble() - 0.5) * 20; // -10到10的风向变化
        double visibilityChange = (_random.NextDouble() - 0.5) * 2; // -1到1的能见度变化
        double temperatureChange = (_random.NextDouble() - 0.5) * 2; // -1到1的温度变化
        
        _currentWeather.WindSpeed = Math.Max(0, Math.Min(50, _currentWeather.WindSpeed + windChange));
        _currentWeather.WindDirection = (_currentWeather.WindDirection + directionChange) % 360;
        _currentWeather.Visibility = Math.Max(0.1, Math.Min(20, _currentWeather.Visibility + visibilityChange));
        _currentWeather.Temperature = Math.Max(-30, Math.Min(45, _currentWeather.Temperature + temperatureChange));
        
        // 随机天气状况
        if (_random.Next(20) == 0) // 5%的概率出现恶劣天气
        {
            string[] severeConditions = { "Thunderstorm", "Heavy Rain", "Snow Storm", "Fog", "Strong Crosswinds" };
            _currentWeather.Conditions = severeConditions[_random.Next(severeConditions.Length)];
            _currentWeather.IsSevere = true;
            
            // 恶劣天气影响风速和能见度
            if (_currentWeather.Conditions == "Thunderstorm" || _currentWeather.Conditions == "Strong Crosswinds")
            {
                _currentWeather.WindSpeed = Math.Max(20, _currentWeather.WindSpeed);
            }
            
            if (_currentWeather.Conditions == "Fog" || _currentWeather.Conditions == "Heavy Rain" || _currentWeather.Conditions == "Snow Storm")
            {
                _currentWeather.Visibility = Math.Min(3, _currentWeather.Visibility);
            }
        }
        else
        {
            string[] normalConditions = { "Clear", "Partly Cloudy", "Cloudy", "Light Rain", "Overcast" };
            _currentWeather.Conditions = normalConditions[_random.Next(normalConditions.Length)];
            _currentWeather.IsSevere = false;
        }
        
        _currentWeather.Timestamp = DateTime.Now;
    }
    
    private void CheckRunwayStatus()
    {
        foreach (var runway in _runways)
        {
            bool shouldBeOperational = true;
            
            // 恶劣天气条件下可能关闭跑道
            if (_currentWeather.IsSevere)
            {
                if (_currentWeather.Conditions == "Fog" && _currentWeather.Visibility < 1)
                {
                    // 大雾时关闭较短的跑道
                    if (runway.Length < 9000)
                    {
                        shouldBeOperational = false;
                    }
                }
                
                if (_currentWeather.Conditions == "Strong Crosswinds" && _currentWeather.WindSpeed > 30)
                {
                    // 强侧风时可能关闭特定方向的跑道
                    double windDir = _currentWeather.WindDirection;
                    if ((runway.Designation.Contains("09") && (windDir > 150 && windDir < 210)) ||
                        (runway.Designation.Contains("27") && (windDir > 330 || windDir < 30)))
                    {
                        shouldBeOperational = false;
                    }
                }
                
                if (_currentWeather.Conditions == "Snow Storm")
                {
                    // 雪暴时随机关闭跑道进行除雪
                    if (_random.Next(3) == 0) // 33%的概率
                    {
                        shouldBeOperational = false;
                    }
                }
            }
            
            // 更新跑道状态
            if (runway.IsOperational != shouldBeOperational)
            {
                runway.IsOperational = shouldBeOperational;
                
                if (shouldBeOperational)
                {
                    SendMessage("Control Tower", $"Runway {runway.Designation} is now operational.", MessageType.SystemAlert);
                }
                else
                {
                    SendMessage("Control Tower", $"Runway {runway.Designation} is now closed due to weather conditions.", MessageType.SystemAlert);
                    
                    // 如果跑道上有飞机,通知它
                    if (runway.IsOccupied && runway.CurrentAircraft != null)
                    {
                        runway.CurrentAircraft.ReceiveMessage("Control Tower", $"Caution: Runway conditions deteriorating. Expedite your operation.", MessageType.Warning);
                    }
                }
            }
        }
    }
    
    private async Task StatusMonitorLoop()
    {
        while (true)
        {
            await Task.Delay(TimeSpan.FromSeconds(30)); // 每30秒检查一次
            
            // 检查每架飞机的状态和燃油情况
            foreach (var aircraft in _registeredAircraft.Values)
            {
                if (aircraft.Status == AircraftStatus.Airborne || 
                    aircraft.Status == AircraftStatus.Approaching || 
                    aircraft.Status == AircraftStatus.OnFinalApproach)
                {
                    // 检查燃油
                    if (aircraft.FuelRemaining < 30) // 少于30分钟的燃油
                    {
                        if (aircraft.FuelRemaining < 15) // 紧急状态
                        {
                            if (!aircraft.HasEmergency)
                            {
                                SendMessage("Control Tower", $"ALERT: {aircraft.CallSign} has less than 15 minutes of fuel remaining!", MessageType.Warning);
                                aircraft.ReceiveMessage("Control Tower", "You have less than 15 minutes of fuel. Declare emergency if needed.", MessageType.Warning);
                            }
                        }
                        else // 警告状态
                        {
                            SendMessage("Control Tower", $"Caution: {aircraft.CallSign} has less than 30 minutes of fuel remaining.", MessageType.Warning);
                            aircraft.ReceiveMessage("Control Tower", "You have less than 30 minutes of fuel. Expedite approach.", MessageType.Warning);
                        }
                    }
                }
            }
            
            // 生成控制台摘要报告
            if (_random.Next(3) == 0) // 33%的概率
            {
                GenerateStatusReport();
            }
        }
    }
    
    private void GenerateStatusReport()
    {
        StringBuilder report = new StringBuilder();
        report.AppendLine("\n===== AIR TRAFFIC CONTROL STATUS REPORT =====");
        report.AppendLine($"Time: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
        report.AppendLine($"Weather: {_currentWeather}");
        report.AppendLine();
        
        report.AppendLine("RUNWAY STATUS:");
        foreach (var runway in _runways)
        {
            report.AppendLine($"- {runway}");
        }
        report.AppendLine();
        
        report.AppendLine("AIRCRAFT STATUS:");
        foreach (var aircraft in _registeredAircraft.Values)
        {
            report.AppendLine($"- {aircraft.CallSign} ({aircraft.Model}): {aircraft.Status}, Position: {aircraft.CurrentPosition}");
        }
        report.AppendLine();
        
        report.AppendLine("QUEUE STATUS:");
        report.AppendLine($"- Landing Queue: {_landingQueue.Count} aircraft");
        report.AppendLine($"- Take-off Queue: {_takeOffQueue.Count} aircraft");
        report.AppendLine($"- Emergency Queue: {_emergencyQueue.Count} aircraft");
        report.AppendLine();
        
        report.AppendLine("GATE USAGE:");
        foreach (var terminal in _occupiedGates.Keys)
        {
            int occupied = _occupiedGates[terminal].Count;
            int total = _gates.Count(g => g.Key.StartsWith(terminal));
            report.AppendLine($"- Terminal {terminal}: {occupied}/{total} gates occupied");
        }
        
        report.AppendLine("============================================");
        
        Console.WriteLine(report.ToString());
    }
    
    public int GetQueuePosition(IAircraft aircraft, OperationType operationType)
    {
        if (operationType == OperationType.Landing)
        {
            int position = 1;
            foreach (var queuedAircraft in _landingQueue)
            {
                if (queuedAircraft.CallSign == aircraft.CallSign)
                {
                    return position;
                }
                position++;
            }
            return -1; // 不在队列中
        }
        else // TakeOff
        {
            int position = 1;
            foreach (var queuedAircraft in _takeOffQueue)
            {
                if (queuedAircraft.CallSign == aircraft.CallSign)
                {
                    return position;
                }
                position++;
            }
            return -1; // 不在队列中
        }
    }
    
    public IReadOnlyList<IAircraft> GetRegisteredAircraft()
    {
        return _registeredAircraft.Values.ToList();
    }
    
    public void AddObserver(IAirTrafficObserver observer)
    {
        if (!_observers.Contains(observer))
        {
            _observers.Add(observer);
        }
    }
    
    public void RemoveObserver(IAirTrafficObserver observer)
    {
        _observers.Remove(observer);
    }
}

// 13. 具体飞机类
public class Aircraft : IAircraft
{
    private readonly IAirTrafficControl _atc;
    private AircraftStatus _status;
    private Position _currentPosition;
    private double _fuelRemaining; // 以分钟为单位
    private bool _hasEmergency;
    private string _emergencyReason;
    private string _currentGate;
    
    public string CallSign { get; }
    public string Model { get; }
    public AircraftType Type { get; }
    
    public AircraftStatus Status => _status;
    public Position CurrentPosition => _currentPosition;
    public double FuelRemaining => _fuelRemaining;
    public bool HasEmergency => _hasEmergency;
    public string CurrentGate => _currentGate;
    
    private readonly Random _random = new Random();
    
    public Aircraft(string callSign, string model, AircraftType type, IAirTrafficControl atc, Position initialPosition, double initialFuel)
    {
        CallSign = callSign;
        Model = model;
        Type = type;
        _atc = atc;
        _currentPosition = initialPosition;
        _fuelRemaining = initialFuel;
        
        // 根据初始位置确定初始状态
        if (initialPosition.Altitude > 1000)
        {
            _status = AircraftStatus.Airborne;
        }
        else
        {
            _status = AircraftStatus.Parked;
        }
        
        // 注册到控制塔台
        _atc.RegisterAircraft(this);
        
        // 定期更新位置和燃油状态
        Task.Run(UpdateLoop);
    }
    
    private async Task UpdateLoop()
    {
        while (true)
        {
            await Task.Delay(5000); // 每5秒更新一次
            
            // 更新燃油
            if (_status == AircraftStatus.Airborne || 
                _status == AircraftStatus.Approaching || 
                _status == AircraftStatus.OnFinalApproach)
            {
                _fuelRemaining -= 5.0 / 60.0; // 每5秒减少5秒的燃油
                
                if (_fuelRemaining <= 10 && !_hasEmergency)
                {
                    // 低燃油紧急情况
                    DeclareEmergency("Low fuel");
                }
            }
            
            // 模拟位置变化
            if (_status == AircraftStatus.Airborne || 
                _status == AircraftStatus.Approaching || 
                _status == AircraftStatus.OnFinalApproach)
            {
                UpdatePosition();
                _atc.ReportPosition(this, _currentPosition);
            }
            
            // 随机事件(非常低概率)
            if (_random.Next(1000) == 0 && !_hasEmergency) // 0.1%的概率
            {
                // 随机技术问题
                string[] emergencyReasons = {
                    "Engine failure",
                    "Hydraulic system malfunction",
                    "Cabin depressurization",
                    "Landing gear issue",
                    "Navigation system failure"
                };
                
                DeclareEmergency(emergencyReasons[_random.Next(emergencyReasons.Length)]);
            }
        }
    }
    
    private void UpdatePosition()
    {
        // 简化的位置更新逻辑,实际应用中应基于航向、速度和目的地
        switch (_status)
        {
            case AircraftStatus.Airborne:
                // 巡航
                _currentPosition.Longitude += (_random.NextDouble() - 0.5) * 0.01;
                _currentPosition.Latitude += (_random.NextDouble() - 0.5) * 0.01;
                break;
                
            case AircraftStatus.Approaching:
                // 下降
                _currentPosition.Altitude = Math.Max(3000, _currentPosition.Altitude - 500);
                _currentPosition.Longitude += (_random.NextDouble() - 0.4) * 0.01; // 向机场移动
                _currentPosition.Latitude += (_random.NextDouble() - 0.4) * 0.01;
                break;
                
            case AircraftStatus.OnFinalApproach:
                // 最终进近
                _currentPosition.Altitude = Math.Max(0, _currentPosition.Altitude - 300);
                _currentPosition.Speed = Math.Max(120, _currentPosition.Speed - 20);
                break;
        }
    }
    
    public void SetStatus(AircraftStatus status)
    {
        _status = status;
    }
    
    public void SetPosition(Position position)
    {
        _currentPosition = position;
    }
    
    public async Task Land(int runwayNumber)
    {
        _atc.SendMessage(CallSign, $"Landing on Runway {runwayNumber}.", MessageType.Information);
        
        // 更新状态为降落中
        SetStatus(AircraftStatus.Landing);
        
        // 模拟降落过程
        await Task.Delay(3000); // 3秒降落时间
        
        // 更新位置和状态
        _currentPosition.Altitude = 0;
        _currentPosition.Speed = 0;
        SetStatus(AircraftStatus.Taxiing);
        
        _atc.SendMessage(CallSign, "Landing completed, taxiing to gate.", MessageType.Information);
        
        // 模拟滑行到登机口
        await Task.Delay(2000); // 2秒滑行时间
        
        // 请求登机口
        var gate = await _atc.RequestGate(this);
        if (gate != null)
        {
            AssignGate(gate);
        }
        else
        {
            SetStatus(AircraftStatus.Parked); // 没有登机口,停在某处
            _atc.SendMessage(CallSign, "Parked at holding position, waiting for gate assignment.", MessageType.Information);
        }
    }
    
    public async Task TakeOff(int runwayNumber)
    {
        _atc.SendMessage(CallSign, $"Taking off from Runway {runwayNumber}.", MessageType.Information);
        
        // 更新状态为起飞中
        SetStatus(AircraftStatus.TakingOff);
        
        // 模拟起飞过程
        await Task.Delay(2000); // 2秒起飞时间
        
        // 更新位置和状态
        _currentPosition.Altitude = 1000; // 初始爬升高度
        _currentPosition.Speed = 200; // 起飞速度
        SetStatus(AircraftStatus.Airborne);
        
        _atc.SendMessage(CallSign, "Take-off completed, climbing to cruise altitude.", MessageType.Information);
        
        // 模拟爬升
        await Task.Delay(1000);
        _currentPosition.Altitude = 5000; // 继续爬升
    }
    
    public async Task EmergencyLand(int runwayNumber)
    {
        _atc.SendMessage(CallSign, $"EMERGENCY LANDING on Runway {runwayNumber}.", MessageType.Emergency);
        
        // 更新状态为紧急操作
        SetStatus(AircraftStatus.EmergencyOperation);
        
        // 模拟紧急降落过程
        await Task.Delay(2500); // 紧急降落稍快
        
        // 更新位置和状态
        _currentPosition.Altitude = 0;
        _currentPosition.Speed = 0;
        
        // 解决紧急情况
        ResolveEmergency();
        
        SetStatus(AircraftStatus.Taxiing);
        
        _atc.SendMessage(CallSign, "Emergency landing completed, taxiing to gate.", MessageType.Information);
        
        // 模拟滑行到登机口
        await Task.Delay(2000);
        
        // 请求登机口
        var gate = await _atc.RequestGate(this);
        if (gate != null)
        {
            AssignGate(gate);
        }
        else
        {
            SetStatus(AircraftStatus.Parked);
            _atc.SendMessage(CallSign, "Parked at holding position, waiting for gate assignment.", MessageType.Information);
        }
    }
    
    public void AssignGate(GateAssignment gate)
    {
        _currentGate = gate.GateNumber;
        SetStatus(AircraftStatus.Parked);
        _atc.SendMessage(CallSign, $"Parked at gate {gate.GateNumber}, Terminal {gate.Terminal}.", MessageType.Information);
    }
    
    public void DeclareEmergency(string reason)
    {
        if (!_hasEmergency)
        {
            _hasEmergency = true;
            _emergencyReason = reason;
            
            _atc.SendMessage(CallSign, $"DECLARING EMERGENCY: {reason}", MessageType.Emergency);
            
            // 通知控制塔台
            if (_status == AircraftStatus.Airborne || 
                _status == AircraftStatus.Approaching || 
                _status == AircraftStatus.OnFinalApproach)
            {
                Task.Run(async () => await _atc.RequestEmergencyLanding(this));
            }
            else
            {
                _atc.SendMessage(CallSign, $"Aircraft on ground declares emergency: {reason}", MessageType.Emergency);
            }
        }
    }
    
    public void ResolveEmergency()
    {
        if (_hasEmergency)
        {
            _hasEmergency = false;
            _atc.SendMessage(CallSign, $"Emergency situation resolved: {_emergencyReason}", MessageType.Information);
            _emergencyReason = null;
        }
    }
    
    public void SendMessage(string message)
    {
        _atc.SendMessage(CallSign, message, MessageType.Information);
    }
    
    public void ReceiveMessage(string from, string message, MessageType type)
    {
        // 处理接收到的消息
        Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Message to {CallSign} from {from}: {message}");
        
        // 如果是来自控制塔台的命令,可以自动执行一些操作
        if (from == "Control Tower" && type == MessageType.ControllerCommand)
        {
            // 模拟飞机对控制塔台命令的自动响应
            if (message.Contains("cleared for landing"))
            {
                SetStatus(AircraftStatus.OnFinalApproach);
            }
            else if (message.Contains("cleared for take-off"))
            {
                SetStatus(AircraftStatus.TakingOff);
            }
            else if (message.Contains("hold"))
            {
                // 进入等待模式
                if (_status == AircraftStatus.Approaching)
                {
                    _atc.SendMessage(CallSign, "Entering holding pattern as instructed.", MessageType.Information);
                }
            }
        }
    }
}

// 14. 日志观察者
public class AirTrafficLogger : IAirTrafficObserver
{
    private readonly string _logFilePath;
    private readonly List<string> _messageBuffer = new List<string>();
    private readonly object _logLock = new object();
    
    public AirTrafficLogger(string logFilePath)
    {
        _logFilePath = logFilePath;
        
        // 创建日志文件
        Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
        File.WriteAllText(logFilePath, $"=== Air Traffic Control Log Started at {DateTime.Now} ===\n");
        
        // 启动定期写入日志的任务
        Task.Run(FlushLogBufferPeriodically);
    }
    
    public void Update(string message, MessageType messageType)
    {
        string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [{messageType}] {message}";
        
        lock (_logLock)
        {
            _messageBuffer.Add(logMessage);
        }
    }
    
    public void UpdateAircraftStatus(IAircraft aircraft, AircraftStatus oldStatus, AircraftStatus newStatus)
    {
        string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [Status] Aircraft {aircraft.CallSign} status changed: {oldStatus} -> {newStatus}";
        
        lock (_logLock)
        {
            _messageBuffer.Add(logMessage);
        }
    }
    
    public void UpdateRunwayStatus(Runway runway, bool wasOccupied, bool isOccupied)
    {
        string statusChange = isOccupied ? "now occupied" : "now free";
        string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [Runway] Runway {runway.Designation} is {statusChange}";
        
        if (isOccupied && runway.CurrentAircraft != null)
        {
            logMessage += $" by {runway.CurrentAircraft.CallSign}";
        }
        
        lock (_logLock)
        {
            _messageBuffer.Add(logMessage);
        }
    }
    
    public void UpdateWeather(WeatherInfo weatherInfo)
    {
        string severity = weatherInfo.IsSevere ? "SEVERE" : "Normal";
        string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [Weather] {severity}: {weatherInfo}";
        
        lock (_logLock)
        {
            _messageBuffer.Add(logMessage);
        }
    }
    
    private async Task FlushLogBufferPeriodically()
    {
        while (true)
        {
            await Task.Delay(10000); // 每10秒写入一次日志
            
            FlushLogBuffer();
        }
    }
    
    private void FlushLogBuffer()
    {
        List<string> messagesToWrite;
        
        lock (_logLock)
        {
            if (_messageBuffer.Count == 0)
                return;
                
            messagesToWrite = new List<string>(_messageBuffer);
            _messageBuffer.Clear();
        }
        
        try
        {
            File.AppendAllLines(_logFilePath, messagesToWrite);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error writing to log file: {ex.Message}");
        }
    }
}

// 15. 显示控制台 - 用于监控整个系统
public class AirTrafficDisplay : IAirTrafficObserver
{
    private readonly List<string> _recentMessages = new List<string>();
    private readonly Dictionary<string, IAircraft> _trackedAircraft = new Dictionary<string, IAircraft>();
    private readonly List<Runway> _runways = new List<Runway>();
    private WeatherInfo _currentWeather;
    private readonly int _maxRecentMessages = 10;
    
    public void Update(string message, MessageType messageType)
    {
        // 保留最近的消息
        lock (_recentMessages)
        {
            _recentMessages.Add($"[{messageType}] {message}");
            
            while (_recentMessages.Count > _maxRecentMessages)
            {
                _recentMessages.RemoveAt(0);
            }
        }
    }
    
    public void UpdateAircraftStatus(IAircraft aircraft, AircraftStatus oldStatus, AircraftStatus newStatus)
    {
        // 更新跟踪的飞机状态
        lock (_trackedAircraft)
        {
            if (!_trackedAircraft.ContainsKey(aircraft.CallSign))
            {
                _trackedAircraft[aircraft.CallSign] = aircraft;
            }
        }
    }
    
    public void UpdateRunwayStatus(Runway runway, bool wasOccupied, bool isOccupied)
    {
        // 更新跟踪的跑道状态
        lock (_runways)
        {
            if (!_runways.Contains(runway))
            {
                _runways.Add(runway);
            }
        }
    }
    
    public void UpdateWeather(WeatherInfo weatherInfo)
    {
        _currentWeather = weatherInfo;
    }
    
    public void DisplayStatus()
    {
        Console.Clear();
        
        // 显示天气信息
        Console.WriteLine("=== AIR TRAFFIC CONTROL DISPLAY ===");
        if (_currentWeather != null)
        {
            Console.WriteLine($"Weather: {_currentWeather}");
        }
        Console.WriteLine();
        
        // 显示跑道状态
        Console.WriteLine("RUNWAYS:");
        lock (_runways)
        {
            foreach (var runway in _runways)
            {
                string status = runway.IsOperational ? 
                    (runway.IsOccupied ? $"OCCUPIED by {runway.CurrentAircraft?.CallSign ?? "Unknown"}" : "FREE") : 
                    "CLOSED";
                
                Console.WriteLine($"- Runway {runway.Designation}: {status}");
            }
        }
        Console.WriteLine();
        
        // 显示飞机状态
        Console.WriteLine("AIRCRAFT:");
        lock (_trackedAircraft)
        {
            foreach (var aircraft in _trackedAircraft.Values)
            {
                string statusIndicator = aircraft.Status switch
                {
                    AircraftStatus.EmergencyOperation => "🚨",
                    AircraftStatus.Approaching => "⬇️ ",
                    AircraftStatus.Landing => "⬇️ ",
                    AircraftStatus.TakingOff => "⬆️ ",
                    AircraftStatus.Airborne => "✈️ ",
                    AircraftStatus.Parked => "🅿️ ",
                    AircraftStatus.Taxiing => "🚕",
                    _ => "  "
                };
                
                string fuelInfo = aircraft.Status == AircraftStatus.Airborne || 
                                 aircraft.Status == AircraftStatus.Approaching ? 
                                 $", Fuel: {aircraft.FuelRemaining:F0} min" : "";
                
                string emergencyInfo = aircraft.HasEmergency ? " [EMERGENCY]" : "";
                
                Console.WriteLine($"- {statusIndicator} {aircraft.CallSign} ({aircraft.Model}): {aircraft.Status}{fuelInfo}{emergencyInfo}");
            }
        }
        Console.WriteLine();
        
        // 显示最近消息
        Console.WriteLine("RECENT MESSAGES:");
        lock (_recentMessages)
        {
            foreach (var message in _recentMessages)
            {
                Console.WriteLine($"- {message}");
            }
        }
        
        Console.WriteLine("\nPress 'Q' to exit the display");
    }
    
    public void StartDisplayLoop()
    {
        Task.Run(async () =>
        {
            while (true)
            {
                DisplayStatus();
                await Task.Delay(5000); // 每5秒刷新一次
            }
        });
    }
}

// 16. 客户端代码
public class Client
{
    public static async Task Main()
    {
        // 创建中介者 - 高级控制塔台
        IAirTrafficControl controlTower = new AdvancedControlTower();
        
        // 创建并注册观察者
        var logger = new AirTrafficLogger("atc_log.txt");
        controlTower.AddObserver(logger);
        
        var display = new AirTrafficDisplay();
        controlTower.AddObserver(display);
        
        // 启动显示循环
        display.StartDisplayLoop();
        
        // 创建飞机
        var initialPositions = new List<Position>
        {
            new Position(39.8, -104.7, 35000, 270, 450), // 空中
            new Position(0.1, 0.1, 0, 0, 0),             // 地面
            new Position(40.1, -105.2, 25000, 90, 400),  // 空中
            new Position(39.5, -104.9, 15000, 180, 350), // 空中接近机场
            new Position(-0.1, -0.1, 0, 0, 0)            // 地面
        };
        
        var flight1 = new Aircraft("BA287", "Boeing 777", AircraftType.LargeCommercial, controlTower, initialPositions[0], 120);
        var flight2 = new Aircraft("LH492", "Airbus A380", AircraftType.LargeCommercial, controlTower, initialPositions[1], 180);
        var flight3 = new Aircraft("SQ321", "Boeing 787", AircraftType.MediumCommercial, controlTower, initialPositions[2], 90);
        var flight4 = new Aircraft("DL123", "Airbus A320", AircraftType.MediumCommercial, controlTower, initialPositions[3], 60);
        var flight5 = new Aircraft("UA789", "Boeing 737", AircraftType.MediumCommercial, controlTower, initialPositions[4], 150);
        
        // 设置初始状态
        flight1.SetStatus(AircraftStatus.Airborne);
        flight2.SetStatus(AircraftStatus.ReadyForTakeOff);
        flight3.SetStatus(AircraftStatus.Airborne);
        flight4.SetStatus(AircraftStatus.Approaching);
        flight5.SetStatus(AircraftStatus.Parked);
        
        // 模拟空中交通
        flight1.SendMessage("Cruising at 35,000 feet.");
        await Task.Delay(2000);
        
        flight2.SendMessage("Ready for departure.");
        await Task.Delay(2000);
        
        flight3.SendMessage("Descending to 20,000 feet.");
        await Task.Delay(2000);
        
        // 请求降落和起飞
        await controlTower.RequestLanding(flight4); // 已在接近状态
        await Task.Delay(2000);
        
        await controlTower.RequestTakeOff(flight2); // 准备起飞
        await Task.Delay(2000);
        
        await controlTower.RequestLanding(flight3); // 需要排队
        await Task.Delay(10000);
        
        // 模拟紧急情况
        flight1.DeclareEmergency("Engine failure");
        await Task.Delay(15000);
        
        // 添加更多飞机进入系统
        var flight6 = new Aircraft("AA456", "Boeing 777", AircraftType.LargeCommercial, controlTower, 
            new Position(39.3, -104.5, 30000, 300, 430), 110);
        flight6.SetStatus(AircraftStatus.Airborne);
        
        var flight7 = new Aircraft("EK781", "Airbus A350", AircraftType.LargeCommercial, controlTower, 
            new Position(40.2, -105.5, 32000, 120, 440), 130);
        flight7.SetStatus(AircraftStatus.Airborne);
        
        await Task.Delay(5000);
        
        // 请求降落
        await controlTower.RequestLanding(flight6);
        await Task.Delay(2000);
        
        await controlTower.RequestLanding(flight7);
        await Task.Delay(20000);
        
        // 使用直接消息
        controlTower.SendDirectMessage("BA287", "EK781", "Welcome to the area, how's the weather up there?");
        await Task.Delay(2000);
        
        controlTower.SendDirectMessage("EK781", "BA287", "Clear skies and smooth flying!");
        
        // 保持程序运行
        Console.WriteLine("\nPress 'Q' to exit");
        while (Console.ReadKey().Key != ConsoleKey.Q)
        {
            await Task.Delay(100);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873

业务场景结合:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;

// 企业聊天系统 - 使用中介者模式实现跨部门沟通

// 1. 消息类
public class ChatMessage
{
    public string MessageId { get; }
    public string SenderUsername { get; }
    public string Content { get; }
    public string Channel { get; } // 频道/部门/私聊对象
    public DateTime Timestamp { get; }
    public MessagePriority Priority { get; }
    public List<FileAttachment> Attachments { get; } = new List<FileAttachment>();
    public bool IsPrivate { get; }
    public HashSet<string> MentionedUsers { get; } = new HashSet<string>();
    public bool IsEdited { get; set; }
    public bool IsDeleted { get; set; }
    public List<string> ReadBy { get; } = new List<string>();
    public List<Reaction> Reactions { get; } = new List<Reaction>();
    
    public ChatMessage(string senderUsername, string content, string channel, 
        MessagePriority priority = MessagePriority.Normal, bool isPrivate = false)
    {
        MessageId = Guid.NewGuid().ToString();
        SenderUsername = senderUsername;
        Content = content;
        Channel = channel;
        Timestamp = DateTime.Now;
        Priority = priority;
        IsPrivate = isPrivate;
        
        // 检测@提及
        ExtractMentions(content);
    }
    
    private void ExtractMentions(string content)
    {
        // 简单的方式检测@提及
        string[] words = content.Split(' ');
        foreach (var word in words)
        {
            if (word.StartsWith("@") && word.Length > 1)
            {
                string username = word.Substring(1);
                MentionedUsers.Add(username);
            }
        }
    }
    
    public void AddAttachment(FileAttachment attachment)
    {
        Attachments.Add(attachment);
    }
    
    public void AddReaction(string username, ReactionType type)
    {
        // 移除用户之前的反应(如果有)
        Reactions.RemoveAll(r => r.Username == username);
        
        // 添加新反应
        Reactions.Add(new Reaction(username, type));
    }
    
    public void MarkAsReadBy(string username)
    {
        if (!ReadBy.Contains(username))
        {
            ReadBy.Add(username);
        }
    }
    
    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        
        // 格式化输出
        string priorityMark = Priority switch
        {
            MessagePriority.High => "❗ ",
            MessagePriority.Urgent => "🚨 ",
            _ => ""
        };
        
        string privateTag = IsPrivate ? "[私聊] " : "";
        string editedTag = IsEdited ? " (已编辑)" : "";
        string deletedTag = IsDeleted ? " (已删除)" : "";
        
        sb.Append($"{priorityMark}{privateTag}[{Timestamp:HH:mm:ss}] {SenderUsername}: {Content}{editedTag}{deletedTag}");
        
        // 添加附件信息
        if (Attachments.Count > 0)
        {
            sb.Append($" [{Attachments.Count} 个附件]");
        }
        
        // 添加反应信息
        if (Reactions.Count > 0)
        {
            var reactionCounts = new Dictionary<ReactionType, int>();
            foreach (var reaction in Reactions)
            {
                if (!reactionCounts.ContainsKey(reaction.Type))
                {
                    reactionCounts[reaction.Type] = 0;
                }
                reactionCounts[reaction.Type]++;
            }
            
            sb.Append(" | ");
            foreach (var reaction in reactionCounts)
            {
                string emoji = GetReactionEmoji(reaction.Key);
                sb.Append($"{emoji}{reaction.Value} ");
            }
        }
        
        return sb.ToString();
    }
    
    private string GetReactionEmoji(ReactionType type)
    {
        return type switch
        {
            ReactionType.Like => "👍",
            ReactionType.Love => "❤️",
            ReactionType.Laugh => "😄",
            ReactionType.Surprise => "😮",
            ReactionType.Sad => "😢",
            ReactionType.Angry => "😠",
            ReactionType.Thumbsdown => "👎",
            _ => "👍"
        };
    }
}

// 2. 文件附件类
public class FileAttachment
{
    public string FileId { get; }
    public string FileName { get; }
    public long FileSize { get; } // 以字节为单位
    public string ContentType { get; }
    public string UploadedBy { get; }
    public DateTime UploadTime { get; }
    public byte[] FileData { get; } // 简化,实际应用中可能只存储引用
    
    public FileAttachment(string fileName, string contentType, byte[] fileData, string uploadedBy)
    {
        FileId = Guid.NewGuid().ToString();
        FileName = fileName;
        ContentType = contentType;
        FileData = fileData;
        FileSize = fileData.Length;
        UploadedBy = uploadedBy;
        UploadTime = DateTime.Now;
    }
    
    public override string ToString()
    {
        string sizeDisplay = FormatFileSize(FileSize);
        return $"{FileName} ({sizeDisplay}, {ContentType})";
    }
    
    private string FormatFileSize(long bytes)
    {
        string[] sizes = { "B", "KB", "MB", "GB" };
        double len = bytes;
        int order = 0;
        
        while (len >= 1024 && order < sizes.Length - 1)
        {
            order++;
            len /= 1024;
        }
        
        return $"{len:0.##} {sizes[order]}";
    }
}

// 3. 反应类
public class Reaction
{
    public string Username { get; }
    public ReactionType Type { get; }
    public DateTime Timestamp { get; }
    
    public Reaction(string username, ReactionType type)
    {
        Username = username;
        Type = type;
        Timestamp = DateTime.Now;
    }
}

// 4. 消息优先级枚举
public enum MessagePriority
{
    Low,
    Normal,
    High,
    Urgent
}

// 5. 反应类型枚举
public enum ReactionType
{
    Like,
    Love,
    Laugh,
    Surprise,
    Sad,
    Angry,
    Thumbsdown
}

// 6. 用户状态枚举
public enum UserStatus
{
    Online,
    Away,
    DoNotDisturb,
    Offline
}

// 7. 聊天客户端接口
public interface IChatClient
{
    string Username { get; }
    string Department { get; }
    UserStatus Status { get; }
    
    void ReceiveMessage(ChatMessage message);
    void ReceiveNotification(string message, NotificationType type);
    void UpdateUserStatus(string username, UserStatus status);
    Task SendMessage(string message, string channel, MessagePriority priority = MessagePriority.Normal);
    Task SendPrivateMessage(string message, string recipient, MessagePriority priority = MessagePriority.Normal);
    Task SendFileAttachment(string filePath, string channel, string message = "");
    void SetStatus(UserStatus status);
    void JoinChannel(string channel);
    void LeaveChannel(string channel);
    void React(string messageId, ReactionType reaction);
    void MarkAsRead(string messageId);
}

// 8. 聊天服务器(中介者)接口
public interface IChatServer
{
    Task RegisterClient(IChatClient client);
    void UnregisterClient(IChatClient client);
    Task SendMessage(string sender, string message, string channel, MessagePriority priority = MessagePriority.Normal);
    Task SendPrivateMessage(string sender, string message, string recipient, MessagePriority priority = MessagePriority.Normal);
    Task SendFileAttachment(string sender, string fileName, string contentType, byte[] fileData, string channel, string message = "");
    void UpdateUserStatus(string username, UserStatus status);
    void JoinChannel(string username, string channel);
    void LeaveChannel(string username, string channel);
    void AddReaction(string username, string messageId, ReactionType reaction);
    void MarkMessageAsRead(string username, string messageId);
    Task<List<ChatMessage>> GetChannelHistory(string channel, int count = 50);
    Task<List<ChatMessage>> GetPrivateHistory(string user1, string user2, int count = 50);
    List<string> GetChannelMembers(string channel);
    List<string> GetOnlineUsers();
    Dictionary<string, UserStatus> GetAllUserStatuses();
    void CreateChannel(string channelName, string creator, bool isPrivate = false);
    void InviteToChannel(string inviter, string invitee, string channel);
}

// 9. 通知类型枚举
public enum NotificationType
{
    Info,
    Warning,
    Error,
    Success,
    MentionNotification,
    ChannelInvitation
}

// 10. 聊天服务器实现(中介者)
public class ChatServer : IChatServer
{
    private readonly Dictionary<string, IChatClient> _connectedClients = new Dictionary<string, IChatClient>();
    private readonly Dictionary<string, HashSet<string>> _channelMembers = new Dictionary<string, HashSet<string>>();
    private readonly Dictionary<string, List<ChatMessage>> _channelMessages = new Dictionary<string, List<ChatMessage>>();
    private readonly Dictionary<string, List<ChatMessage>> _privateMessages = new Dictionary<string, List<ChatMessage>>();
    private readonly Dictionary<string, bool> _privateChannels = new Dictionary<string, bool>();
    private readonly Dictionary<string, string> _channelCreators = new Dictionary<string, string>();
    private readonly Dictionary<string, ChatMessage> _allMessages = new Dictionary<string, ChatMessage>();
    
    private readonly ILogger<ChatServer> _logger;
    private readonly SemaphoreSlim _clientsLock = new SemaphoreSlim(1, 1);
    private readonly SemaphoreSlim _messagesLock = new SemaphoreSlim(1, 1);
    
    public ChatServer(ILogger<ChatServer> logger)
    {
        _logger = logger;
        
        // 创建默认频道
        CreateChannel("General", "System", false);
        CreateChannel("Random", "System", false);
        CreateChannel("Announcements", "System", false);
    }
    
    public async Task RegisterClient(IChatClient client)
    {
        await _clientsLock.WaitAsync();
        try
        {
            if (!_connectedClients.ContainsKey(client.Username))
            {
                _connectedClients[client.Username] = client;
                
                // 自动加入部门频道
                if (!string.IsNullOrEmpty(client.Department))
                {
                    string departmentChannel = client.Department;
                    
                    // 确保部门频道存在
                    if (!_channelMembers.ContainsKey(departmentChannel))
                    {
                        CreateChannel(departmentChannel, "System", false);
                    }
                    
                    JoinChannel(client.Username, departmentChannel);
                }
                
                // 自动加入General频道
                JoinChannel(client.Username, "General");
                
                // 通知其他用户
                BroadcastUserStatus(client.Username, client.Status);
                
                // 通知用户自己
                string welcomeMessage = $"欢迎加入聊天系统,{client.Username}!你已自动加入 General 频道";
                if (!string.IsNullOrEmpty(client.Department))
                {
                    welcomeMessage += $" 和 {client.Department} 频道";
                }
                welcomeMessage += "。";
                
                client.ReceiveNotification(welcomeMessage, NotificationType.Info);
                
                _logger.LogInformation("用户 {Username} 已连接", client.Username);
            }
            else
            {
                throw new InvalidOperationException($"用户名 {client.Username} 已被使用");
            }
        }
        finally
        {
            _clientsLock.Release();
        }
    }
    
    public void UnregisterClient(IChatClient client)
    {
        _clientsLock.Wait();
        try
        {
            if (_connectedClients.ContainsKey(client.Username))
            {
                _connectedClients.Remove(client.Username);
                
                // 更新所有频道
                foreach (var channel in _channelMembers.Keys.ToList())
                {
                    if (_channelMembers[channel].Contains(client.Username))
                    {
                        _channelMembers[channel].Remove(client.Username);
                    }
                }
                
                // 通知其他用户
                BroadcastUserStatus(client.Username, UserStatus.Offline);
                
                _logger.LogInformation("用户 {Username} 已断开连接", client.Username);
            }
        }
        finally
        {
            _clientsLock.Release();
        }
    }
    
    public async Task SendMessage(string sender, string message, string channel, MessagePriority priority = MessagePriority.Normal)
    {
        // 验证用户是否是频道成员
        if (!IsChannelMember(sender, channel))
        {
            _logger.LogWarning("用户 {Username} 尝试在非成员频道 {Channel} 发送消息", sender, channel);
            
            if (_connectedClients.TryGetValue(sender, out IChatClient client))
            {
                client.ReceiveNotification($"你不是 {channel} 频道的成员,无法发送消息", NotificationType.Error);
            }
            
            return;
        }
        
        // 创建消息
        var chatMessage = new ChatMessage(sender, message, channel, priority);
        
        await _messagesLock.WaitAsync();
        try
        {
            // 存储消息
            if (!_channelMessages.ContainsKey(channel))
            {
                _channelMessages[channel] = new List<ChatMessage>();
            }
            
            _channelMessages[channel].Add(chatMessage);
            _allMessages[chatMessage.MessageId] = chatMessage;
            
            _logger.LogInformation("用户 {Username} 在频道 {Channel} 发送消息: {Message}", 
                sender, channel, message);
        }
        finally
        {
            _messagesLock.Release();
        }
        
        // 将消息发送给频道所有成员
        await DeliverMessageToChannel(chatMessage, channel);
    }
    
    public async Task SendPrivateMessage(string sender, string message, string recipient, MessagePriority priority = MessagePriority.Normal)
    {
        // 验证接收者存在
        if (!_connectedClients.ContainsKey(recipient))
        {
            _logger.LogWarning("用户 {Username} 尝试向不存在的用户 {Recipient} 发送私信", sender, recipient);
            
            if (_connectedClients.TryGetValue(sender, out IChatClient client))
            {
                client.ReceiveNotification($"用户 {recipient} 不存在或已离线", NotificationType.Error);
            }
            
            return;
        }
        
        // 创建私聊消息
        var chatMessage = new ChatMessage(sender, message, recipient, priority, true);
        
        await _messagesLock.WaitAsync();
        try
        {
            // 存储私聊消息
            string privateKey = GetPrivateMessageKey(sender, recipient);
            
            if (!_privateMessages.ContainsKey(privateKey))
            {
                _privateMessages[privateKey] = new List<ChatMessage>();
            }
            
            _privateMessages[privateKey].Add(chatMessage);
            _allMessages[chatMessage.MessageId] = chatMessage;
            
            _logger.LogInformation("用户 {Username} 向 {Recipient} 发送私信: {Message}", 
                sender, recipient, message);
        }
        finally
        {
            _messagesLock.Release();
        }
        
        // 发送给发送者和接收者
        if (_connectedClients.TryGetValue(sender, out IChatClient senderClient))
        {
            senderClient.ReceiveMessage(chatMessage);
        }
        
        if (_connectedClients.TryGetValue(recipient, out IChatClient recipientClient))
        {
            recipientClient.ReceiveMessage(chatMessage);
        }
    }
    
    public async Task SendFileAttachment(string sender, string fileName, string contentType, byte[] fileData, string channel, string message = "")
    {
        // 创建文件附件
        var attachment = new FileAttachment(fileName, contentType, fileData, sender);
        
        // 创建消息
        string fileMessage = string.IsNullOrEmpty(message) ? 
            $"分享了文件: {fileName}" : message;
            
        var chatMessage = new ChatMessage(sender, fileMessage, channel);
        chatMessage.AddAttachment(attachment);
        
        await _messagesLock.WaitAsync();
        try
        {
            // 存储消息
            if (channel.StartsWith("@")) // 私聊文件
            {
                string recipient = channel.Substring(1);
                string privateKey = GetPrivateMessageKey(sender, recipient);
                
                if (!_privateMessages.ContainsKey(privateKey))
                {
                    _privateMessages[privateKey] = new List<ChatMessage>();
                }
                
                _privateMessages[privateKey].Add(chatMessage);
                
                // 发送给接收者
                if (_connectedClients.TryGetValue(recipient, out IChatClient recipientClient))
                {
                    recipientClient.ReceiveMessage(chatMessage);
                }
                
                // 发送给发送者
                if (_connectedClients.TryGetValue(sender, out IChatClient senderClient))
                {
                    senderClient.ReceiveMessage(chatMessage);
                }
            }
            else // 频道文件
            {
                if (!_channelMessages.ContainsKey(channel))
                {
                    _channelMessages[channel] = new List<ChatMessage>();
                }
                
                _channelMessages[channel].Add(chatMessage);
                
                // 发送给所有频道成员
                await DeliverMessageToChannel(chatMessage, channel);
            }
            
            _allMessages[chatMessage.MessageId] = chatMessage;
            
            _logger.LogInformation("用户 {Username} 在 {Channel} 分享了文件: {FileName} ({FileSize} 字节)", 
                sender, channel, fileName, fileData.Length);
        }
        finally
        {
            _messagesLock.Release();
        }
    }
    
    private async Task DeliverMessageToChannel(ChatMessage message, string channel)
    {
        await _clientsLock.WaitAsync();
        try
        {
            if (_channelMembers.TryGetValue(channel, out var members))
            {
                foreach (var member in members)
                {
                    if (_connectedClients.TryGetValue(member, out IChatClient client))
                    {
                        client.ReceiveMessage(message);
                        
                        // 处理@提及通知
                        if (message.MentionedUsers.Contains(member))
                        {
                            string notification = $"你被 {message.SenderUsername} 在 {channel} 频道中提及了";
                            client.ReceiveNotification(notification, NotificationType.MentionNotification);
                        }
                    }
                }
            }
        }
        finally
        {
            _clientsLock.Release();
        }
    }
    
    public void UpdateUserStatus(string username, UserStatus status)
    {
        _clientsLock.Wait();
        try
        {
            if (_connectedClients.ContainsKey(username))
            {
                // 通知所有客户端
                BroadcastUserStatus(username, status);
                
                _logger.LogInformation("用户 {Username} 状态更新为: {Status}", username, status);
            }
        }
        finally
        {
            _clientsLock.Release();
        }
    }
    
    private void BroadcastUserStatus(string username, UserStatus status)
    {
        foreach (var client in _connectedClients.Values)
        {
            client.UpdateUserStatus(username, status);
        }
    }
    
    public void JoinChannel(string username, string channel)
    {
        _clientsLock.Wait();
        try
        {
            // 检查频道是否存在
            if (!_channelMembers.ContainsKey(channel))
            {
                _logger.LogWarning("用户 {Username} 尝试加入不存在的频道: {Channel}", username, channel);
                
                if (_connectedClients.TryGetValue(username, out IChatClient client))
                {
                    client.ReceiveNotification($"频道 {channel} 不存在", NotificationType.Error);
                }
                
                return;
            }
            
            // 检查是否为私有频道,且用户没有被邀请
            if (_privateChannels.TryGetValue(channel, out bool isPrivate) && isPrivate)
            {
                if (!_channelMembers[channel].Contains(username))
                {
                    _logger.LogWarning("用户 {Username} 尝试加入未被邀请的私有频道: {Channel}", username, channel);
                    
                    if (_connectedClients.TryGetValue(username, out IChatClient client))
                    {
                        client.ReceiveNotification($"频道 {channel} 是私有的,需要邀请才能加入", NotificationType.Error);
                    }
                    
                    return;
                }
            }
            
            // 添加用户到频道
            _channelMembers[channel].Add(username);
            
            // 通知频道其他成员
            foreach (var member in _channelMembers[channel])
            {
                if (member != username && _connectedClients.TryGetValue(member, out IChatClient client))
                {
                    client.ReceiveNotification($"{username} 加入了 {channel} 频道", NotificationType.Info);
                }
            }
            
            // 通知用户自己
            if (_connectedClients.TryGetValue(username, out IChatClient joinedClient))
            {
                joinedClient.ReceiveNotification($"你已加入 {channel} 频道", NotificationType.Success);
            }
            
            _logger.LogInformation("用户 {Username} 加入频道: {Channel}", username, channel);
        }
        finally
        {
            _clientsLock.Release();
        }
    }
    
    public void LeaveChannel(string username, string channel)
    {
        _clientsLock.Wait();
        try
        {
            if (_channelMembers.ContainsKey(channel) && _channelMembers[channel].Contains(username))
            {
                _channelMembers[channel].Remove(username);
                
                // 通知频道其他成员
                foreach (var member in _channelMembers[channel])
                {
                    if (_connectedClients.TryGetValue(member, out IChatClient client))
                    {
                        client.ReceiveNotification($"{username} 离开了 {channel} 频道", NotificationType.Info);
                    }
                }
                
                // 通知用户自己
                if (_connectedClients.TryGetValue(username, out IChatClient leavingClient))
                {
                    leavingClient.ReceiveNotification($"你已离开 {channel} 频道", NotificationType.Info);
                }
                
                _logger.LogInformation("用户 {Username} 离开频道: {Channel}", username, channel);
            }
        }
        finally
        {
            _clientsLock.Release();
        }
    }
    
    public void AddReaction(string username, string messageId, ReactionType reaction)
    {
        _messagesLock.Wait();
        try
        {
            if (_allMessages.TryGetValue(messageId, out ChatMessage message))
            {
                message.AddReaction(username, reaction);
                
                _logger.LogInformation("用户 {Username} 对消息 {MessageId} 添加了反应: {Reaction}", 
                    username, messageId, reaction);
                    
                // 如果是频道消息,通知频道成员
                if (!message.IsPrivate && _channelMembers.TryGetValue(message.Channel, out var members))
                {
                    foreach (var member in members)
                    {
                        if (_connectedClients.TryGetValue(member, out IChatClient client))
                        {
                            // 发送更新的消息
                            client.ReceiveMessage(message);
                        }
                    }
                }
                // 如果是私聊消息,通知发送者和接收者
                else if (message.IsPrivate)
                {
                    string sender = message.SenderUsername;
                    string recipient = message.Channel; // 在私聊中,Channel存储的是接收者用户名
                    
                    if (_connectedClients.TryGetValue(sender, out IChatClient senderClient))
                    {
                        senderClient.ReceiveMessage(message);
                    }
                    
                    if (_connectedClients.TryGetValue(recipient, out IChatClient recipientClient))
                    {
                        recipientClient.ReceiveMessage(message);
                    }
                }
            }
        }
        finally
        {
            _messagesLock.Release();
        }
    }
    
    public void MarkMessageAsRead(string username, string messageId)
    {
        _messagesLock.Wait();
        try
        {
            if (_allMessages.TryGetValue(messageId, out ChatMessage message))
            {
                message.MarkAsReadBy(username);
                
                _logger.LogDebug("用户 {Username} 已读消息 {MessageId}", username, messageId);
            }
        }
        finally
        {
            _messagesLock.Release();
        }
    }
    
    public async Task<List<ChatMessage>> GetChannelHistory(string channel, int count = 50)
    {
        await _messagesLock.WaitAsync();
        try
        {
            if (_channelMessages.TryGetValue(channel, out var messages))
            {
                return messages.OrderByDescending(m => m.Timestamp).Take(count).Reverse().ToList();
            }
            
            return new List<ChatMessage>();
        }
        finally
        {
            _messagesLock.Release();
        }
    }
    
    public async Task<List<ChatMessage>> GetPrivateHistory(string user1, string user2, int count = 50)
    {
        await _messagesLock.WaitAsync();
        try
        {
            string privateKey = GetPrivateMessageKey(user1, user2);
            
            if (_privateMessages.TryGetValue(privateKey, out var messages))
            {
                return messages.OrderByDescending(m => m.Timestamp).Take(count).Reverse().ToList();
            }
            
            return new List<ChatMessage>();
        }
        finally
        {
            _messagesLock.Release();
        }
    }
    
    public List<string> GetChannelMembers(string channel)
    {
        _clientsLock.Wait();
        try
        {
            if (_channelMembers.TryGetValue(channel, out var members))
            {
                return members.ToList();
            }
            
            return new List<string>();
        }
        finally
        {
            _clientsLock.Release();
        }
    }
    
    public List<string> GetOnlineUsers()
    {
        _clientsLock.Wait();
        try
        {
            return _connectedClients.Keys.ToList();
        }
        finally
        {
            _clientsLock.Release();
        }
    }
    
    public Dictionary<string, UserStatus> GetAllUserStatuses()
    {
        _clientsLock.Wait();
        try
        {
            var statuses = new Dictionary<string, UserStatus>();
            
            foreach (var client in _connectedClients)
            {
                statuses[client.Key] = client.Value.Status;
            }
            
            return statuses;
        }
        finally
        {
            _clientsLock.Release();
        }
    }
    
    public void CreateChannel(string channelName, string creator, bool isPrivate = false)
    {
        _clientsLock.Wait();
        try
        {
            if (!_channelMembers.ContainsKey(channelName))
            {
                _channelMembers[channelName] = new HashSet<string>();
                _privateChannels[channelName] = isPrivate;
                _channelCreators[channelName] = creator;
                
                // 将创建者加入频道
                if (creator != "System")
                {
                    _channelMembers[channelName].Add(creator);
                }
                
                _logger.LogInformation("用户 {Username} 创建了{PrivateFlag}频道: {Channel}", 
                    creator, isPrivate ? "私有" : "", channelName);
                    
                // 通知创建者
                if (creator != "System" && _connectedClients.TryGetValue(creator, out IChatClient client))
                {
                    client.ReceiveNotification($"你已成功创建{(isPrivate ? "私有" : "")}频道: {channelName}", NotificationType.Success);
                }
                
                // 如果不是私有频道,通知所有用户
                if (!isPrivate)
                {
                    foreach (var c in _connectedClients.Values)
                    {
                        if (c.Username != creator)
                        {
                            c.ReceiveNotification($"新频道已创建: {channelName}", NotificationType.Info);
                        }
                    }
                }
            }
            else
            {
                _logger.LogWarning("用户 {Username} 尝试创建已存在的频道: {Channel}", creator, channelName);
                
                if (_connectedClients.TryGetValue(creator, out IChatClient client))
                {
                    client.ReceiveNotification($"频道 {channelName} 已存在", NotificationType.Error);
                }
            }
        }
        finally
        {
            _clientsLock.Release();
        }
    }
    
    public void InviteToChannel(string inviter, string invitee, string channel)
    {
        _clientsLock.Wait();
        try
        {
            // 检查频道是否存在
            if (!_channelMembers.ContainsKey(channel))
            {
                _logger.LogWarning("用户 {Username} 尝试邀请用户到不存在的频道: {Channel}", inviter, channel);
                
                if (_connectedClients.TryGetValue(inviter, out IChatClient client))
                {
                    client.ReceiveNotification($"频道 {channel} 不存在", NotificationType.Error);
                }
                
                return;
            }
            
            // 检查邀请者是否是频道成员
            if (!_channelMembers[channel].Contains(inviter))
            {
                _logger.LogWarning("非频道成员 {Username} 尝试邀请用户到频道: {Channel}", inviter, channel);
                
                if (_connectedClients.TryGetValue(inviter, out IChatClient client))
                {
                    client.ReceiveNotification($"你不是频道 {channel} 的成员,无法邀请其他用户", NotificationType.Error);
                }
                
                return;
            }
            
            // 检查被邀请者是否存在
            if (!_connectedClients.ContainsKey(invitee))
            {
                _logger.LogWarning("用户 {Username} 尝试邀请不存在的用户 {Invitee} 到频道: {Channel}", 
                    inviter, invitee, channel);
                    
                if (_connectedClients.TryGetValue(inviter, out IChatClient client))
                {
                    client.ReceiveNotification($"用户 {invitee} 不存在或已离线", NotificationType.Error);
                }
                
                return;
            }
            
            // 检查被邀请者是否已经是频道成员
            if (_channelMembers[channel].Contains(invitee))
            {
                _logger.LogWarning("用户 {Username} 尝试邀请已经是频道成员的用户 {Invitee} 到频道: {Channel}", 
                    inviter, invitee, channel);
                    
                if (_connectedClients.TryGetValue(inviter, out IChatClient client))
                {
                    client.ReceiveNotification($"用户 {invitee} 已经是频道 {channel} 的成员", NotificationType.Warning);
                }
                
                return;
            }
            
            // 处理邀请
            _channelMembers[channel].Add(invitee);
            
            _logger.LogInformation("用户 {Username} 邀请了 {Invitee} 到频道: {Channel}", 
                inviter, invitee, channel);
                
            // 通知被邀请者
            if (_connectedClients.TryGetValue(invitee, out IChatClient inviteeClient))
            {
                inviteeClient.ReceiveNotification($"{inviter} 邀请你加入频道 {channel}", NotificationType.ChannelInvitation);
                inviteeClient.JoinChannel(channel);
            }
            
            // 通知邀请者
            if (_connectedClients.TryGetValue(inviter, out IChatClient inviterClient))
            {
                inviterClient.ReceiveNotification($"已成功邀请 {invitee} 加入频道 {channel}", NotificationType.Success);
            }
            
            // 通知频道其他成员
            foreach (var member in _channelMembers[channel])
            {
                if (member != inviter && member != invitee && _connectedClients.TryGetValue(member, out IChatClient client))
                {
                    client.ReceiveNotification($"{invitee} 被 {inviter} 邀请加入了频道", NotificationType.Info);
                }
            }
        }
        finally
        {
            _clientsLock.Release();
        }
    }
    
    private bool IsChannelMember(string username, string channel)
    {
        return _channelMembers.ContainsKey(channel) && _channelMembers[channel].Contains(username);
    }
    
    private string GetPrivateMessageKey(string user1, string user2)
    {
        // 确保键的顺序一致
        var users = new[] { user1, user2 }.OrderBy(u => u).ToArray();
        return $"{users[0]}:{users[1]}";
    }
}

// 11. 聊天客户端实现
public class ChatClient : IChatClient
{
    private readonly IChatServer _server;
    private readonly ILogger<ChatClient> _logger;
    private readonly List<string> _joinedChannels = new List<string>();
    private readonly Dictionary<string, UserStatus> _userStatuses = new Dictionary<string, UserStatus>();
    
    public string Username { get; }
    public string Department { get; }
    public UserStatus Status { get; private set; }
    
    public ChatClient(string username, string department, IChatServer server, ILogger<ChatClient> logger)
    {
        Username = username;
        Department = department;
        Status = UserStatus.Online;
        _server = server;
        _logger = logger;
    }
    
    public async Task Initialize()
    {
        await _server.RegisterClient(this);
        
        // 获取频道历史消息
        foreach (var channel in _joinedChannels)
        {
            var history = await _server.GetChannelHistory(channel);
            
            foreach (var message in history)
            {
                Console.WriteLine($"[历史消息] {message}");
            }
        }
    }
    
    public void ReceiveMessage(ChatMessage message)
    {
        // 在实际应用中,这里会将消息显示在UI上
        Console.WriteLine($"[{message.Channel}] {message}");
        
        // 标记消息为已读
        _server.MarkMessageAsRead(Username, message.MessageId);
    }
    
    public void ReceiveNotification(string message, NotificationType type)
    {
        string prefix = type switch
        {
            NotificationType.Warning => "⚠️ ",
            NotificationType.Error => "❌ ",
            NotificationType.Success => "✅ ",
            NotificationType.MentionNotification => "🔔 ",
            NotificationType.ChannelInvitation => "📩 ",
            _ => "ℹ️ "
        };
        
        Console.WriteLine($"{prefix}通知: {message}");
    }
    
    public void UpdateUserStatus(string username, UserStatus status)
    {
        _userStatuses[username] = status;
        
        // 在实际应用中,这里会更新UI上的用户状态
        _logger.LogDebug("用户 {OtherUser} 状态更新为: {Status}", username, status);
    }
    
    public async Task SendMessage(string message, string channel, MessagePriority priority = MessagePriority.Normal)
    {
        await _server.SendMessage(Username, message, channel, priority);
    }
    
    public async Task SendPrivateMessage(string message, string recipient, MessagePriority priority = MessagePriority.Normal)
    {
        await _server.SendPrivateMessage(Username, message, recipient, priority);
    }
    
    public async Task SendFileAttachment(string filePath, string channel, string message = "")
    {
        try
        {
            if (!File.Exists(filePath))
            {
                ReceiveNotification($"文件不存在: {filePath}", NotificationType.Error);
                return;
            }
            
            string fileName = Path.GetFileName(filePath);
            string contentType = GetContentType(filePath);
            byte[] fileData = await File.ReadAllBytesAsync(filePath);
            
            await _server.SendFileAttachment(Username, fileName, contentType, fileData, channel, message);
        }
        catch (Exception ex)
        {
            ReceiveNotification($"发送文件失败: {ex.Message}", NotificationType.Error);
            _logger.LogError(ex, "用户 {Username} 发送文件 {FilePath} 失败", Username, filePath);
        }
    }
    
    private string GetContentType(string filePath)
    {
        string extension = Path.GetExtension(filePath).ToLower();
        
        return extension switch
        {
            ".txt" => "text/plain",
            ".pdf" => "application/pdf",
            ".doc" or ".docx" => "application/msword",
            ".xls" or ".xlsx" => "application/vnd.ms-excel",
            ".png" => "image/png",
            ".jpg" or ".jpeg" => "image/jpeg",
            ".gif" => "image/gif",
            _ => "application/octet-stream"
        };
    }
    
    public void SetStatus(UserStatus status)
    {
        Status = status;
        _server.UpdateUserStatus(Username, status);
    }
    
    public void JoinChannel(string channel)
    {
        if (!_joinedChannels.Contains(channel))
        {
            _joinedChannels.Add(channel);
            _server.JoinChannel(Username, channel);
        }
    }
    
    public void LeaveChannel(string channel)
    {
        if (_joinedChannels.Contains(channel))
        {
            _joinedChannels.Remove(channel);
            _server.LeaveChannel(Username, channel);
        }
    }
    
    public void React(string messageId, ReactionType reaction)
    {
        _server.AddReaction(Username, messageId, reaction);
    }
    
    public void MarkAsRead(string messageId)
    {
        _server.MarkMessageAsRead(Username, messageId);
    }
    
    public void Disconnect()
    {
        _server.UnregisterClient(this);
    }
    
    public List<string> GetJoinedChannels()
    {
        return new List<string>(_joinedChannels);
    }
    
    public Dictionary<string, UserStatus> GetUserStatuses()
    {
        return new Dictionary<string, UserStatus>(_userStatuses);
    }
}

// 12. 控制台聊天客户端
public class ConsoleChatClient
{
    private readonly IChatClient _client;
    private readonly IChatServer _server;
    private bool _running = true;
    private string _currentChannel = "General";
    
    public ConsoleChatClient(IChatClient client, IChatServer server)
    {
        _client = client;
        _server = server;
    }
    
    public async Task Run()
    {
        // 显示欢迎信息
        Console.WriteLine($"欢迎使用企业聊天系统,{_client.Username}!");
        Console.WriteLine("输入 /help 查看可用命令");
        Console.WriteLine($"当前频道: {_currentChannel}");
        
        // 显示频道历史消息
        await ShowChannelHistory(_currentChannel);
        
        // 启动接收消息的任务
        // 注意:在真实的应用中,消息接收会由UI框架处理
        
        // 处理用户输入
        while (_running)
        {
            Console.Write($"[{_currentChannel}] > ");
            string input = Console.ReadLine();
            
            if (string.IsNullOrEmpty(input))
                continue;
                
            await ProcessInput(input);
        }
    }
    
    private async Task ProcessInput(string input)
    {
        if (input.StartsWith("/"))
        {
            // 命令处理
            string[] parts = input.Split(' ', 2);
            string command = parts[0].ToLower();
            string args = parts.Length > 1 ? parts[1] : "";
            
            switch (command)
            {
                case "/help":
                    ShowHelp();
                    break;
                    
                case "/quit":
                case "/exit":
                    _running = false;
                    _client.SetStatus(UserStatus.Offline);
                    ((ChatClient)_client).Disconnect();
                    Console.WriteLine("再见!");
                    break;
                    
                case "/join":
                    if (!string.IsNullOrEmpty(args))
                    {
                        _client.JoinChannel(args);
                        _currentChannel = args;
                        await ShowChannelHistory(_currentChannel);
                    }
                    break;
                    
                case "/leave":
                    string channelToLeave = string.IsNullOrEmpty(args) ? _currentChannel : args;
                    _client.LeaveChannel(channelToLeave);
                    if (channelToLeave == _currentChannel)
                    {
                        _currentChannel = "General";
                        await ShowChannelHistory(_currentChannel);
                    }
                    break;
                    
                case "/channel":
                case "/ch":
                    if (!string.IsNullOrEmpty(args))
                    {
                        _currentChannel = args;
                        await ShowChannelHistory(_currentChannel);
                    }
                    break;
                    
                case "/list":
                    ListChannels();
                    break;
                    
                case "/members":
                    ListMembers(string.IsNullOrEmpty(args) ? _currentChannel : args);
                    break;
                    
                case "/msg":
                case "/pm":
                    await SendPrivateMessage(args);
                    break;
                    
                case "/status":
                    SetStatus(args);
                    break;
                    
                case "/users":
                    ListUsers();
                    break;
                    
                case "/create":
                    CreateChannel(args);
                    break;
                    
                case "/invite":
                    InviteUser(args);
                    break;
                    
                case "/file":
                    await SendFile(args);
                    break;
                    
                case "/history":
                    await ShowHistory(args);
                    break;
                    
                default:
                    Console.WriteLine($"未知命令: {command}");
                    break;
            }
        }
        else
        {
            // 发送普通消息
            MessagePriority priority = MessagePriority.Normal;
            
            // 检查是否有优先级标记
            if (input.StartsWith("!"))
            {
                priority = MessagePriority.High;
                input = input.Substring(1);
            }
            else if (input.StartsWith("!!"))
            {
                priority = MessagePriority.Urgent;
                input = input.Substring(2);
            }
            
            await _client.SendMessage(input, _currentChannel, priority);
        }
    }
    
    private void ShowHelp()
    {
        Console.WriteLine("可用命令:");
        Console.WriteLine("  /help - 显示帮助");
        Console.WriteLine("  /quit 或 /exit - 退出");
        Console.WriteLine("  /join <频道> - 加入频道");
        Console.WriteLine("  /leave [频道] - 离开当前频道或指定频道");
        Console.WriteLine("  /channel 或 /ch <频道> - 切换当前频道");
        Console.WriteLine("  /list - 列出所有可用频道");
        Console.WriteLine("  /members [频道] - 列出频道成员");
        Console.WriteLine("  /msg 或 /pm <用户> <消息> - 发送私信");
        Console.WriteLine("  /status <状态> - 设置状态 (online, away, dnd, offline)");
        Console.WriteLine("  /users - 列出在线用户");
        Console.WriteLine("  /create <频道名> [private] - 创建新频道");
        Console.WriteLine("  /invite <用户> [频道] - 邀请用户加入频道");
        Console.WriteLine("  /file <文件路径> [消息] - 发送文件");
        Console.WriteLine("  /history [频道/用户] [数量] - 显示历史消息");
        Console.WriteLine("消息前缀:");
        Console.WriteLine("  ! - 高优先级消息");
        Console.WriteLine("  !! - 紧急消息");
    }
    
    private async Task ShowChannelHistory(string channel)
    {
        Console.WriteLine($"=== {channel} 频道 ===");
        
        var history = await _server.GetChannelHistory(channel, 10);
        
        if (history.Count == 0)
        {
            Console.WriteLine("(没有历史消息)");
        }
        else
        {
            foreach (var message in history)
            {
                Console.WriteLine(message);
            }
        }
        
        Console.WriteLine("==================");
    }
    
    private void ListChannels()
    {
        var joinedChannels = ((ChatClient)_client).GetJoinedChannels();
        
        Console.WriteLine("已加入的频道:");
        foreach (var channel in joinedChannels)
        {
            string currentMark = channel == _currentChannel ? " (当前)" : "";
            Console.WriteLine($"- {channel}{currentMark}");
        }
    }
    
    private void ListMembers(string channel)
    {
        var members = _server.GetChannelMembers(channel);
        
        Console.WriteLine($"{channel} 频道成员 ({members.Count}):");
        foreach (var member in members)
        {
            var status = ((ChatClient)_client).GetUserStatuses().TryGetValue(member, out UserStatus userStatus) 
                ? userStatus 
                : UserStatus.Offline;
                
            string statusIcon = status switch
            {
                UserStatus.Online => "🟢",
                UserStatus.Away => "🟡",
                UserStatus.DoNotDisturb => "🔴",
                UserStatus.Offline => "⚫",
                _ => "⚪"
            };
            
            Console.WriteLine($"- {statusIcon} {member}");
        }
    }
    
    private async Task SendPrivateMessage(string args)
    {
        string[] parts = args.Split(' ', 2);
        
        if (parts.Length < 2)
        {
            Console.WriteLine("用法: /msg <用户> <消息>");
            return;
        }
        
        string recipient = parts[0];
        string message = parts[1];
        
        await _client.SendPrivateMessage(message, recipient);
    }
    
    private void SetStatus(string status)
    {
        UserStatus newStatus = status.ToLower() switch
        {
            "online" => UserStatus.Online,
            "away" => UserStatus.Away,
            "dnd" => UserStatus.DoNotDisturb,
            "offline" => UserStatus.Offline,
            _ => _client.Status // 保持不变
        };
        
        if (newStatus != _client.Status)
        {
            _client.SetStatus(newStatus);
            Console.WriteLine($"状态已更新为: {newStatus}");
        }
    }
    
    private void ListUsers()
    {
        var userStatuses = ((ChatClient)_client).GetUserStatuses();
        
        Console.WriteLine("用户列表:");
        foreach (var user in userStatuses)
        {
            string statusIcon = user.Value switch
            {
                UserStatus.Online => "🟢",
                UserStatus.Away => "🟡",
                UserStatus.DoNotDisturb => "🔴",
                UserStatus.Offline => "⚫",
                _ => "⚪"
            };
            
            Console.WriteLine($"- {statusIcon} {user.Key}");
        }
    }
    
    private void CreateChannel(string args)
    {
        string[] parts = args.Split(' ', 2);
        string channelName = parts[0];
        bool isPrivate = parts.Length > 1 && parts[1].Trim().ToLower() == "private";
        
        _server.CreateChannel(channelName, _client.Username, isPrivate);
    }
    
    private void InviteUser(string args)
    {
        string[] parts = args.Split(' ', 2);
        
        if (parts.Length == 0)
        {
            Console.WriteLine("用法: /invite <用户> [频道]");
            return;
        }
        
        string invitee = parts[0];
        string channel = parts.Length > 1 ? parts[1] : _currentChannel;
        
        _server.InviteToChannel(_client.Username, invitee, channel);
    }
    
    private async Task SendFile(string args)
    {
        string[] parts = args.Split(' ', 2);
        
        if (parts.Length == 0)
        {
            Console.WriteLine("用法: /file <文件路径> [消息]");
            return;
        }
        
        string filePath = parts[0];
        string message = parts.Length > 1 ? parts[1] : "";
        
        await _client.SendFileAttachment(filePath, _currentChannel, message);
    }
    
    private async Task ShowHistory(string args)
    {
        string target = _currentChannel;
        int count = 10;
        
        string[] parts = args.Split(' ');
        
        if (parts.Length > 0 && !string.IsNullOrEmpty(parts[0]))
        {
            target = parts[0];
        }
        
        if (parts.Length > 1 && int.TryParse(parts[1], out int parsedCount))
        {
            count = Math.Min(parsedCount, 50); // 限制最大数量
        }
        
        // 检查是用户还是频道
        if (target.StartsWith("@"))
        {
            string user = target.Substring(1);
            await ShowPrivateHistory(user, count);
        }
        else
        {
            await ShowChannelHistory(target, count);
        }
    }
    
    private async Task ShowChannelHistory(string channel, int count)
    {
        var history = await _server.GetChannelHistory(channel, count);
        
        Console.WriteLine($"=== {channel} 频道的最近 {count} 条消息 ===");
        
        if (history.Count == 0)
        {
            Console.WriteLine("(没有历史消息)");
        }
        else
        {
            foreach (var message in history)
            {
                Console.WriteLine(message);
            }
        }
        
        Console.WriteLine("==================");
    }
    
    private async Task ShowPrivateHistory(string otherUser, int count)
    {
        var history = await _server.GetPrivateHistory(_client.Username, otherUser, count);
        
        Console.WriteLine($"=== 与 {otherUser} 的最近 {count} 条私聊消息 ===");
        
        if (history.Count == 0)
        {
            Console.WriteLine("(没有历史消息)");
        }
        else
        {
            foreach (var message in history)
            {
                Console.WriteLine(message);
            }
        }
        
        Console.WriteLine("==================");
    }
}

// 13. 客户端代码
public class Program
{
    public static async Task Main()
    {
        // 设置依赖注入
        var services = new ServiceCollection();
        
        // 添加日志
        services.AddLogging(builder =>
        {
            builder.AddConsole();
            builder.SetMinimumLevel(LogLevel.Information);
        });
        
        // 注册服务
        services.AddSingleton<IChatServer, ChatServer>();
        
        var serviceProvider = services.BuildServiceProvider();
        
        // 获取聊天服务器
        var chatServer = serviceProvider.GetRequiredService<IChatServer>();
        
        // 创建客户端
        Console.Write("请输入用户名: ");
        string username = Console.ReadLine() ?? "Guest";
        
        Console.Write("请输入部门: ");
        string department = Console.ReadLine() ?? "General";
        
        var logger = serviceProvider.GetRequiredService<ILoggerFactory>().CreateLogger<ChatClient>();
        
        // 创建并初始化客户端
        var chatClient = new ChatClient(username, department, chatServer, logger);
        await chatClient.Initialize();
        
        // 创建并运行控制台客户端
        var consoleClient = new ConsoleChatClient(chatClient, chatServer);
        await consoleClient.Run();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624

# 17. 备忘录模式

原理:
备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便在稍后可以将对象恢复到原先保存的状态。

思路:

  1. 创建发起者类,包含需要保存的状态和创建备忘录的方法
  2. 创建备忘录类,用于存储发起者的内部状态
  3. 创建负责人类,负责保存和恢复备忘录
  4. 客户端通过发起者创建备忘录,并将其交给负责人保存

前辈经验:

  • 当需要提供撤销功能或保存对象状态用于恢复时,使用备忘录模式
  • 备忘录模式可以防止发起者的内部状态暴露给外部
  • 注意备忘录可能占用大量内存,可以考虑增量快照或限制历史记录数量
  • 备忘录内容应该只能由原发起者访问,以维护封装性
  • 在多线程环境中使用备忘录模式需要额外的同步措施

业务场景:
文本编辑器,需要实现撤销/重做功能,保存用户编辑的各个状态。

简单实现:

// 备忘录类 - 存储文本编辑器的状态
public class TextEditorMemento
{
    // 只读属性,保证备忘录对象不可变
    public string Text { get; }
    public int CursorPosition { get; }
    public DateTime SavedTime { get; }
    
    public TextEditorMemento(string text, int cursorPosition)
    {
        Text = text;
        CursorPosition = cursorPosition;
        SavedTime = DateTime.Now;
    }
}

// 发起者类 - 文本编辑器
public class TextEditor
{
    private string _text;
    private int _cursorPosition;
    
    public TextEditor()
    {
        _text = string.Empty;
        _cursorPosition = 0;
    }
    
    // 获取当前文本
    public string GetText()
    {
        return _text;
    }
    
    // 获取当前光标位置
    public int GetCursorPosition()
    {
        return _cursorPosition;
    }
    
    // 在光标位置插入文本
    public void InsertText(string text)
    {
        _text = _text.Insert(_cursorPosition, text);
        _cursorPosition += text.Length;
    }
    
    // 删除指定数量的字符
    public void DeleteText(int count)
    {
        if (_cursorPosition >= count)
        {
            _text = _text.Remove(_cursorPosition - count, count);
            _cursorPosition -= count;
        }
    }
    
    // 移动光标
    public void MoveCursor(int position)
    {
        if (position >= 0 && position <= _text.Length)
        {
            _cursorPosition = position;
        }
    }
    
    // 创建备忘录
    public TextEditorMemento CreateMemento()
    {
        return new TextEditorMemento(_text, _cursorPosition);
    }
    
    // 从备忘录恢复
    public void RestoreFromMemento(TextEditorMemento memento)
    {
        _text = memento.Text;
        _cursorPosition = memento.CursorPosition;
    }
    
    // 显示当前编辑器状态
    public void Display()
    {
        Console.WriteLine($"文本: '{_text}'");
        Console.WriteLine($"光标位置: {_cursorPosition}");
        
        // 显示带光标的文本
        string displayText = _text.Insert(_cursorPosition, "|");
        Console.WriteLine($"可视化: {displayText}");
    }
}

// 负责人类 - 历史记录管理器
public class EditorHistory
{
    private readonly Stack<TextEditorMemento> _undoStack = new Stack<TextEditorMemento>();
    private readonly Stack<TextEditorMemento> _redoStack = new Stack<TextEditorMemento>();
    
    // 保存状态
    public void SaveState(TextEditorMemento memento)
    {
        _undoStack.Push(memento);
        // 每次保存新状态时,清空重做栈
        _redoStack.Clear();
    }
    
    // 撤销
    public TextEditorMemento Undo()
    {
        if (_undoStack.Count <= 1)
        {
            Console.WriteLine("无法撤销:已经是最早的状态");
            return _undoStack.Peek();
        }
        
        TextEditorMemento current = _undoStack.Pop();
        _redoStack.Push(current);
        return _undoStack.Peek();
    }
    
    // 重做
    public TextEditorMemento Redo()
    {
        if (_redoStack.Count == 0)
        {
            Console.WriteLine("无法重做:没有被撤销的操作");
            return null;
        }
        
        TextEditorMemento memento = _redoStack.Pop();
        _undoStack.Push(memento);
        return memento;
    }
    
    // 获取撤销栈大小
    public int UndoCount()
    {
        return _undoStack.Count;
    }
    
    // 获取重做栈大小
    public int RedoCount()
    {
        return _redoStack.Count;
    }
    
    // 显示历史记录
    public void DisplayHistory()
    {
        Console.WriteLine("\n历史记录:");
        Console.WriteLine($"可撤销操作数: {_undoStack.Count}");
        Console.WriteLine($"可重做操作数: {_redoStack.Count}");
        
        if (_undoStack.Count > 0)
        {
            Console.WriteLine("最近的编辑状态:");
            int count = 0;
            foreach (var memento in _undoStack)
            {
                if (count++ >= 3) break; // 只显示最近3个状态
                Console.WriteLine($"- '{memento.Text}' [光标: {memento.CursorPosition}, 时间: {memento.SavedTime.ToLongTimeString()}]");
            }
        }
    }
}

// 客户端代码
public class Client
{
    public static void Main()
    {
        TextEditor editor = new TextEditor();
        EditorHistory history = new EditorHistory();
        
        // 初始状态
        Console.WriteLine("=== 初始状态 ===");
        editor.Display();
        history.SaveState(editor.CreateMemento());
        
        // 操作1:插入文本
        editor.InsertText("Hello");
        Console.WriteLine("\n=== 插入 'Hello' 后 ===");
        editor.Display();
        history.SaveState(editor.CreateMemento());
        
        // 操作2:继续插入文本
        editor.InsertText(", World!");
        Console.WriteLine("\n=== 插入 ', World!' 后 ===");
        editor.Display();
        history.SaveState(editor.CreateMemento());
        
        // 操作3:移动光标
        editor.MoveCursor(5);
        Console.WriteLine("\n=== 移动光标到位置5后 ===");
        editor.Display();
        history.SaveState(editor.CreateMemento());
        
        // 操作4:插入文本
        editor.InsertText(" beautiful");
        Console.WriteLine("\n=== 插入 ' beautiful' 后 ===");
        editor.Display();
        history.SaveState(editor.CreateMemento());
        
        // 显示历史记录
        history.DisplayHistory();
        
        // 撤销
        Console.WriteLine("\n=== 撤销操作 ===");
        TextEditorMemento memento = history.Undo();
        editor.RestoreFromMemento(memento);
        editor.Display();
        
        // 再次撤销
        Console.WriteLine("\n=== 再次撤销 ===");
        memento = history.Undo();
        editor.RestoreFromMemento(memento);
        editor.Display();
        
        // 重做
        Console.WriteLine("\n=== 重做操作 ===");
        memento = history.Redo();
        if (memento != null)
        {
            editor.RestoreFromMemento(memento);
            editor.Display();
        }
        
        // 新操作
        Console.WriteLine("\n=== 执行新操作 ===");
        editor.InsertText(" amazing");
        editor.Display();
        history.SaveState(editor.CreateMemento());
        
        // 显示更新后的历史记录
        history.DisplayHistory();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236

复杂实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Text.Json;
using System.Text.Json.Serialization;

// 1. 操作类型枚举
public enum EditOperationType
{
    Insert,
    Delete,
    Replace,
    MoveCursor,
    Format,
    SelectText,
    ApplyStyle,
    Undo,
    Redo,
    Save
}

// 2. 样式类
public class TextStyle
{
    public bool IsBold { get; set; }
    public bool IsItalic { get; set; }
    public bool IsUnderlined { get; set; }
    public string FontName { get; set; } = "Arial";
    public int FontSize { get; set; } = 12;
    public string TextColor { get; set; } = "Black";
    public string BackgroundColor { get; set; } = "White";
    
    public TextStyle Clone()
    {
        return new TextStyle
        {
            IsBold = this.IsBold,
            IsItalic = this.IsItalic,
            IsUnderlined = this.IsUnderlined,
            FontName = this.FontName,
            FontSize = this.FontSize,
            TextColor = this.TextColor,
            BackgroundColor = this.BackgroundColor
        };
    }
    
    public override string ToString()
    {
        List<string> styles = new List<string>();
        if (IsBold) styles.Add("Bold");
        if (IsItalic) styles.Add("Italic");
        if (IsUnderlined) styles.Add("Underlined");
        
        return $"{FontName}, {FontSize}pt, {TextColor}, {string.Join(", ", styles)}";
    }
}

// 3. 文本选择范围
public class TextSelection
{
    public int StartPosition { get; set; }
    public int EndPosition { get; set; }
    
    public bool HasSelection => EndPosition > StartPosition;
    
    public int Length => EndPosition - StartPosition;
    
    public TextSelection(int startPosition, int endPosition)
    {
        StartPosition = startPosition;
        EndPosition = endPosition;
    }
    
    public TextSelection Clone()
    {
        return new TextSelection(StartPosition, EndPosition);
    }
}

// 4. 编辑操作类 - 命令模式与备忘录模式结合
public abstract class EditOperation
{
    public string OperationId { get; }
    public EditOperationType OperationType { get; }
    public DateTime Timestamp { get; }
    public string Description { get; }
    
    protected EditOperation(EditOperationType operationType, string description)
    {
        OperationId = Guid.NewGuid().ToString();
        OperationType = operationType;
        Timestamp = DateTime.Now;
        Description = description;
    }
    
    public abstract void Execute(TextDocument document);
    public abstract void Undo(TextDocument document);
}

// 5. 具体操作类 - 插入文本
public class InsertTextOperation : EditOperation
{
    public string Text { get; }
    public int Position { get; }
    
    public InsertTextOperation(string text, int position) 
        : base(EditOperationType.Insert, $"Insert '{text}' at position {position}")
    {
        Text = text;
        Position = position;
    }
    
    public override void Execute(TextDocument document)
    {
        document.InsertTextInternal(Position, Text);
    }
    
    public override void Undo(TextDocument document)
    {
        document.DeleteTextInternal(Position, Text.Length);
    }
}

// 6. 具体操作类 - 删除文本
public class DeleteTextOperation : EditOperation
{
    public int Position { get; }
    public int Length { get; }
    public string DeletedText { get; private set; }
    
    public DeleteTextOperation(int position, int length)
        : base(EditOperationType.Delete, $"Delete {length} characters from position {position}")
    {
        Position = position;
        Length = length;
    }
    
    public override void Execute(TextDocument document)
    {
        // 保存要删除的文本,以便撤销
        DeletedText = document.GetTextInternal(Position, Length);
        document.DeleteTextInternal(Position, Length);
    }
    
    public override void Undo(TextDocument document)
    {
        document.InsertTextInternal(Position, DeletedText);
    }
}

// 7. 具体操作类 - 替换文本
public class ReplaceTextOperation : EditOperation
{
    public int Position { get; }
    public int Length { get; }
    public string NewText { get; }
    public string OldText { get; private set; }
    
    public ReplaceTextOperation(int position, int length, string newText)
        : base(EditOperationType.Replace, $"Replace {length} characters with '{newText}' at position {position}")
    {
        Position = position;
        Length = length;
        NewText = newText;
    }
    
    public override void Execute(TextDocument document)
    {
        // 保存要替换的文本,以便撤销
        OldText = document.GetTextInternal(Position, Length);
        document.ReplaceTextInternal(Position, Length, NewText);
    }
    
    public override void Undo(TextDocument document)
    {
        document.ReplaceTextInternal(Position, NewText.Length, OldText);
    }
}

// 8. 具体操作类 - 移动光标
public class MoveCursorOperation : EditOperation
{
    public int NewPosition { get; }
    public int OldPosition { get; private set; }
    
    public MoveCursorOperation(int newPosition)
        : base(EditOperationType.MoveCursor, $"Move cursor to position {newPosition}")
    {
        NewPosition = newPosition;
    }
    
    public override void Execute(TextDocument document)
    {
        OldPosition = document.CursorPosition;
        document.MoveCursorInternal(NewPosition);
    }
    
    public override void Undo(TextDocument document)
    {
        document.MoveCursorInternal(OldPosition);
    }
}

// 9. 具体操作类 - 选择文本
public class SelectTextOperation : EditOperation
{
    public int StartPosition { get; }
    public int EndPosition { get; }
    public TextSelection OldSelection { get; private set; }
    
    public SelectTextOperation(int startPosition, int endPosition)
        : base(EditOperationType.SelectText, $"Select text from position {startPosition} to {endPosition}")
    {
        StartPosition = startPosition;
        EndPosition = endPosition;
    }
    
    public override void Execute(TextDocument document)
    {
        OldSelection = document.Selection?.Clone();
        document.SelectTextInternal(StartPosition, EndPosition);
    }
    
    public override void Undo(TextDocument document)
    {
        if (OldSelection != null)
        {
            document.SelectTextInternal(OldSelection.StartPosition, OldSelection.EndPosition);
        }
        else
        {
            document.ClearSelectionInternal();
        }
    }
}

// 10. 具体操作类 - 应用样式
public class ApplyStyleOperation : EditOperation
{
    public TextStyle NewStyle { get; }
    public TextStyle OldStyle { get; private set; }
    public int Position { get; }
    public int Length { get; }
    
    public ApplyStyleOperation(int position, int length, TextStyle style)
        : base(EditOperationType.ApplyStyle, $"Apply style at position {position} for {length} characters")
    {
        Position = position;
        Length = length;
        NewStyle = style.Clone();
    }
    
    public override void Execute(TextDocument document)
    {
        OldStyle = document.GetStyleInternal(Position, Length);
        document.ApplyStyleInternal(Position, Length, NewStyle);
    }
    
    public override void Undo(TextDocument document)
    {
        document.ApplyStyleInternal(Position, Length, OldStyle);
    }
}

// 11. 操作组 - 多个操作作为一个单元
public class OperationGroup : EditOperation
{
    private readonly List<EditOperation> _operations = new List<EditOperation>();
    
    public OperationGroup(string description)
        : base(EditOperationType.Insert, description)
    {
    }
    
    public void AddOperation(EditOperation operation)
    {
        _operations.Add(operation);
    }
    
    public override void Execute(TextDocument document)
    {
        foreach (var operation in _operations)
        {
            operation.Execute(document);
        }
    }
    
    public override void Undo(TextDocument document)
    {
        // 按相反顺序撤销操作
        for (int i = _operations.Count - 1; i >= 0; i--)
        {
            _operations[i].Undo(document);
        }
    }
    
    public int OperationCount => _operations.Count;
}

// 12. 备忘录类 - 存储文档的状态
public class DocumentMemento
{
    public string Text { get; }
    public int CursorPosition { get; }
    public TextSelection Selection { get; }
    public Dictionary<string, TextStyle> Styles { get; }
    public DateTime SavedTime { get; }
    public string Description { get; }
    public string OperationId { get; }
    
    // 创建完整备忘录
    public DocumentMemento(string text, int cursorPosition, TextSelection selection, 
                          Dictionary<string, TextStyle> styles, string description, string operationId)
    {
        Text = text;
        CursorPosition = cursorPosition;
        Selection = selection?.Clone();
        Styles = styles != null ? new Dictionary<string, TextStyle>(styles) : new Dictionary<string, TextStyle>();
        SavedTime = DateTime.Now;
        Description = description;
        OperationId = operationId;
    }
    
    // 将备忘录序列化为JSON
    public string Serialize()
    {
        var options = new JsonSerializerOptions { WriteIndented = true };
        return JsonSerializer.Serialize(this, options);
    }
    
    // 从JSON反序列化备忘录
    public static DocumentMemento Deserialize(string json)
    {
        return JsonSerializer.Deserialize<DocumentMemento>(json);
    }
    
    // 保存备忘录到文件
    public void SaveToFile(string filePath)
    {
        string json = Serialize();
        File.WriteAllText(filePath, json);
    }
    
    // 从文件加载备忘录
    public static DocumentMemento LoadFromFile(string filePath)
    {
        string json = File.ReadAllText(filePath);
        return Deserialize(json);
    }
}

// 13. 文档类 - 发起者
public class TextDocument
{
    // 文档状态
    private StringBuilder _text = new StringBuilder();
    private int _cursorPosition = 0;
    private TextSelection _selection = null;
    private Dictionary<string, TextStyle> _styles = new Dictionary<string, TextStyle>();
    
    // 监控变更的标志
    private bool _isDirty = false;
    private DateTime _lastSaveTime = DateTime.MinValue;
    private string _filePath = null;
    
    // 自动保存相关
    private Timer _autoSaveTimer;
    private readonly int _autoSaveInterval = 60000; // 60秒
    
    // 事件
    public event EventHandler<DocumentChangedEventArgs> DocumentChanged;
    public event EventHandler<DocumentSavedEventArgs> DocumentSaved;
    public event EventHandler<DocumentMementoCreatedEventArgs> MementoCreated;
    
    // 属性
    public string Text => _text.ToString();
    public int CursorPosition => _cursorPosition;
    public TextSelection Selection => _selection;
    public bool IsDirty => _isDirty;
    public DateTime LastSaveTime => _lastSaveTime;
    public string FilePath => _filePath;
    
    // 构造函数
    public TextDocument()
    {
        // 设置自动保存计时器
        _autoSaveTimer = new Timer(AutoSave, null, _autoSaveInterval, _autoSaveInterval);
    }
    
    public TextDocument(string initialText) : this()
    {
        _text.Append(initialText);
    }
    
    // 自动保存回调
    private void AutoSave(object state)
    {
        if (_isDirty && !string.IsNullOrEmpty(_filePath))
        {
            SaveToFile(_filePath);
            
            // 创建自动保存备忘录
            var memento = CreateMemento("Auto-save");
            OnMementoCreated(memento);
        }
    }
    
    // 公共方法 - 创建备忘录
    public DocumentMemento CreateMemento(string description = "Manual save")
    {
        string operationId = Guid.NewGuid().ToString();
        
        var memento = new DocumentMemento(
            _text.ToString(), 
            _cursorPosition,
            _selection,
            _styles,
            description,
            operationId
        );
        
        return memento;
    }
    
    // 公共方法 - 从备忘录恢复
    public void RestoreFromMemento(DocumentMemento memento)
    {
        _text = new StringBuilder(memento.Text);
        _cursorPosition = memento.CursorPosition;
        _selection = memento.Selection?.Clone();
        _styles = new Dictionary<string, TextStyle>(memento.Styles);
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = ChangeType.FullRestore,
            Description = $"Restored from state: {memento.Description}"
        });
    }
    
    // 公共方法 - 执行操作
    public void ExecuteOperation(EditOperation operation)
    {
        operation.Execute(this);
        _isDirty = true;
    }
    
    // 内部方法 - 供操作类使用
    internal void InsertTextInternal(int position, string text)
    {
        if (position < 0 || position > _text.Length)
            throw new ArgumentOutOfRangeException(nameof(position));
            
        _text.Insert(position, text);
        _cursorPosition = position + text.Length;
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = ChangeType.TextInserted,
            Position = position,
            Length = text.Length,
            Text = text
        });
    }
    
    internal void DeleteTextInternal(int position, int length)
    {
        if (position < 0 || position + length > _text.Length)
            throw new ArgumentOutOfRangeException(nameof(position));
            
        string deletedText = _text.ToString(position, length);
        _text.Remove(position, length);
        _cursorPosition = position;
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = ChangeType.TextDeleted,
            Position = position,
            Length = length,
            Text = deletedText
        });
    }
    
    internal void ReplaceTextInternal(int position, int length, string newText)
    {
        if (position < 0 || position + length > _text.Length)
            throw new ArgumentOutOfRangeException(nameof(position));
            
        string oldText = _text.ToString(position, length);
        _text.Remove(position, length);
        _text.Insert(position, newText);
        _cursorPosition = position + newText.Length;
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = ChangeType.TextReplaced,
            Position = position,
            Length = length,
            Text = oldText,
            NewText = newText
        });
    }
    
    internal void MoveCursorInternal(int position)
    {
        if (position < 0 || position > _text.Length)
            throw new ArgumentOutOfRangeException(nameof(position));
            
        int oldPosition = _cursorPosition;
        _cursorPosition = position;
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = ChangeType.CursorMoved,
            Position = position,
            OldPosition = oldPosition
        });
    }
    
    internal void SelectTextInternal(int startPosition, int endPosition)
    {
        if (startPosition < 0 || startPosition > _text.Length ||
            endPosition < 0 || endPosition > _text.Length)
            throw new ArgumentOutOfRangeException();
            
        _selection = new TextSelection(startPosition, endPosition);
        _cursorPosition = endPosition;
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = ChangeType.TextSelected,
            Position = startPosition,
            Length = endPosition - startPosition
        });
    }
    
    internal void ClearSelectionInternal()
    {
        _selection = null;
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = ChangeType.SelectionCleared
        });
    }
    
    internal TextStyle GetStyleInternal(int position, int length)
    {
        string key = $"{position}:{length}";
        if (_styles.TryGetValue(key, out TextStyle style))
        {
            return style.Clone();
        }
        
        return new TextStyle(); // 返回默认样式
    }
    
    internal void ApplyStyleInternal(int position, int length, TextStyle style)
    {
        string key = $"{position}:{length}";
        _styles[key] = style.Clone();
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = ChangeType.StyleApplied,
            Position = position,
            Length = length,
            Style = style
        });
    }
    
    internal string GetTextInternal(int position, int length)
    {
        if (position < 0 || position + length > _text.Length)
            throw new ArgumentOutOfRangeException();
            
        return _text.ToString(position, length);
    }
    
    // 公共方法 - 文档操作
    public void InsertText(string text)
    {
        var operation = new InsertTextOperation(text, _cursorPosition);
        ExecuteOperation(operation);
    }
    
    public void DeleteText(int length)
    {
        if (_cursorPosition < length)
            throw new ArgumentOutOfRangeException(nameof(length));
            
        var operation = new DeleteTextOperation(_cursorPosition - length, length);
        ExecuteOperation(operation);
    }
    
    public void ReplaceText(int startPosition, int length, string newText)
    {
        var operation = new ReplaceTextOperation(startPosition, length, newText);
        ExecuteOperation(operation);
    }
    
    public void MoveCursor(int position)
    {
        var operation = new MoveCursorOperation(position);
        ExecuteOperation(operation);
    }
    
    public void SelectText(int startPosition, int endPosition)
    {
        var operation = new SelectTextOperation(startPosition, endPosition);
        ExecuteOperation(operation);
    }
    
    public void ApplyStyle(TextStyle style)
    {
        if (_selection == null)
            return;
            
        var operation = new ApplyStyleOperation(_selection.StartPosition, _selection.Length, style);
        ExecuteOperation(operation);
    }
    
    // 保存文件方法
    public void SaveToFile(string filePath)
    {
        File.WriteAllText(filePath, _text.ToString());
        _filePath = filePath;
        _lastSaveTime = DateTime.Now;
        _isDirty = false;
        
        OnDocumentSaved(new DocumentSavedEventArgs
        {
            FilePath = filePath,
            SaveTime = _lastSaveTime
        });
    }
    
    // 加载文件方法
    public void LoadFromFile(string filePath)
    {
        if (!File.Exists(filePath))
            throw new FileNotFoundException("文件不存在", filePath);
            
        string content = File.ReadAllText(filePath);
        _text = new StringBuilder(content);
        _cursorPosition = 0;
        _selection = null;
        _styles.Clear();
        _filePath = filePath;
        _lastSaveTime = File.GetLastWriteTime(filePath);
        _isDirty = false;
        
        OnDocumentChanged(new DocumentChangedEventArgs
        {
            ChangeType = ChangeType.FullRestore,
            Description = $"Loaded from file: {filePath}"
        });
    }
    
    // 显示文档内容
    public void Display()
    {
        Console.WriteLine($"文档内容 ({_text.Length} 字符):");
        
        // 限制显示长度
        string displayText = _text.ToString();
        if (displayText.Length > 100)
        {
            displayText = displayText.Substring(0, 97) + "...";
        }
        
        // 添加光标位置标记
        if (_selection != null)
        {
            // 显示选中的文本
            string beforeSelection = displayText.Substring(0, _selection.StartPosition);
            string selectedText = displayText.Substring(_selection.StartPosition, 
                Math.Min(_selection.Length, displayText.Length - _selection.StartPosition));
            string afterSelection = "";
            
            if (_selection.EndPosition < displayText.Length)
            {
                afterSelection = displayText.Substring(_selection.EndPosition);
            }
            
            Console.WriteLine($"{beforeSelection}[{selectedText}]{afterSelection}");
        }
        else
        {
            // 只显示光标
            string beforeCursor = displayText.Substring(0, Math.Min(_cursorPosition, displayText.Length));
            string afterCursor = "";
            
            if (_cursorPosition < displayText.Length)
            {
                afterCursor = displayText.Substring(_cursorPosition);
            }
            
            Console.WriteLine($"{beforeCursor}|{afterCursor}");
        }
        
        Console.WriteLine($"光标位置: {_cursorPosition}");
        
        // 显示样式信息
        if (_styles.Count > 0)
        {
            Console.WriteLine("应用的样式:");
            foreach (var style in _styles)
            {
                string[] parts = style.Key.Split(':');
                int position = int.Parse(parts[0]);
                int length = int.Parse(parts[1]);
                
                Console.WriteLine($"  位置 {position}, 长度 {length}: {style.Value}");
            }
        }
        
        // 显示保存状态
        string dirtyMark = _isDirty ? " *" : "";
        Console.WriteLine($"状态: {(_isDirty ? "未保存" : "已保存")}{dirtyMark}");
        
        if (_lastSaveTime > DateTime.MinValue)
        {
            Console.WriteLine($"最后保存: {_lastSaveTime}");
        }
    }
    
    // 事件触发方法
    protected virtual void OnDocumentChanged(DocumentChangedEventArgs e)
    {
        DocumentChanged?.Invoke(this, e);
    }
    
    protected virtual void OnDocumentSaved(DocumentSavedEventArgs e)
    {
        DocumentSaved?.Invoke(this, e);
    }
    
    protected virtual void OnMementoCreated(DocumentMemento memento)
    {
        MementoCreated?.Invoke(this, new DocumentMementoCreatedEventArgs
        {
            Memento = memento
        });
    }
    
    // 析构函数 - 清理定时器
    ~TextDocument()
    {
        _autoSaveTimer?.Dispose();
    }
}

// 14. 事件参数类
public class DocumentChangedEventArgs : EventArgs
{
    public ChangeType ChangeType { get; set; }
    public int Position { get; set; }
    public int Length { get; set; }
    public int OldPosition { get; set; }
    public string Text { get; set; }
    public string NewText { get; set; }
    public TextStyle Style { get; set; }
    public string Description { get; set; }
}

public class DocumentSavedEventArgs : EventArgs
{
    public string FilePath { get; set; }
    public DateTime SaveTime { get; set; }
}

public class DocumentMementoCreatedEventArgs : EventArgs
{
    public DocumentMemento Memento { get; set; }
}

// 15. 变更类型枚举
public enum ChangeType
{
    TextInserted,
    TextDeleted,
    TextReplaced,
    CursorMoved,
    TextSelected,
    SelectionCleared,
    StyleApplied,
    FullRestore
}

// 16. 历史管理器 - 负责人
public class DocumentHistoryManager
{
    private readonly Stack<DocumentMemento> _undoStack = new Stack<DocumentMemento>();
    private readonly Stack<DocumentMemento> _redoStack = new Stack<DocumentMemento>();
    private readonly TextDocument _document;
    private readonly int _maxHistorySize;
    private bool _isUndoRedoOperation = false;
    
    public event EventHandler<HistoryChangedEventArgs> HistoryChanged;
    
    public DocumentHistoryManager(TextDocument document, int maxHistorySize = 100)
    {
        _document = document;
        _maxHistorySize = maxHistorySize;
        
        // 订阅文档变更事件
        _document.DocumentChanged += Document_Changed;
        _document.MementoCreated += Document_MementoCreated;
        
        // 保存初始状态
        SaveState("初始状态");
    }
    
    private void Document_Changed(object sender, DocumentChangedEventArgs e)
    {
        if (!_isUndoRedoOperation && e.ChangeType != ChangeType.FullRestore)
        {
            // 当文档变更时,自动保存状态
            SaveState(GetDescriptionForChange(e));
        }
    }
    
    private void Document_MementoCreated(object sender, DocumentMementoCreatedEventArgs e)
    {
        if (!_isUndoRedoOperation)
        {
            // 处理外部创建的备忘录
            AddToUndoStack(e.Memento);
        }
    }
    
    private string GetDescriptionForChange(DocumentChangedEventArgs e)
    {
        return e.ChangeType switch
        {
            ChangeType.TextInserted => $"插入文本 '{e.Text}'",
            ChangeType.TextDeleted => $"删除文本 '{e.Text}'",
            ChangeType.TextReplaced => $"替换文本 '{e.Text}' 为 '{e.NewText}'",
            ChangeType.CursorMoved => $"移动光标到位置 {e.Position}",
            ChangeType.TextSelected => $"选择文本,从位置 {e.Position} 开始,长度 {e.Length}",
            ChangeType.SelectionCleared => "清除选择",
            ChangeType.StyleApplied => $"应用样式到位置 {e.Position},长度 {e.Length}",
            ChangeType.FullRestore => e.Description ?? "完全恢复",
            _ => "文档变更"
        };
    }
    
    // 保存状态
    public void SaveState(string description = "手动保存")
    {
        var memento = _document.CreateMemento(description);
        AddToUndoStack(memento);
    }
    
    private void AddToUndoStack(DocumentMemento memento)
    {
        _undoStack.Push(memento);
        
        // 限制历史记录大小
        while (_undoStack.Count > _maxHistorySize)
        {
            _undoStack.Pop();
        }
        
        // 清空重做栈
        _redoStack.Clear();
        
        OnHistoryChanged();
    }
    
    // 撤销
    public void Undo()
    {
        if (_undoStack.Count <= 1)
        {
            Console.WriteLine("无法撤销:已经是最早的状态");
            return;
        }
        
        _isUndoRedoOperation = true;
        try
        {
            DocumentMemento current = _undoStack.Pop();
            _redoStack.Push(current);
            
            DocumentMemento previous = _undoStack.Peek();
            _document.RestoreFromMemento(previous);
            
            Console.WriteLine($"撤销操作: {current.Description}");
            
            OnHistoryChanged();
        }
        finally
        {
            _isUndoRedoOperation = false;
        }
    }
    
    // 重做
    public void Redo()
    {
        if (_redoStack.Count == 0)
        {
            Console.WriteLine("无法重做:没有被撤销的操作");
            return;
        }
        
        _isUndoRedoOperation = true;
        try
        {
            DocumentMemento memento = _redoStack.Pop();
            _undoStack.Push(memento);
            _document.RestoreFromMemento(memento);
            
            Console.WriteLine($"重做操作: {memento.Description}");
            
            OnHistoryChanged();
        }
        finally
        {
            _isUndoRedoOperation = false;
        }
    }
    
    // 保存历史记录到文件
    public void SaveHistoryToFile(string filePath)
    {
        List<string> serializedStates = new List<string>();
        
        foreach (var memento in _undoStack)
        {
            serializedStates.Add(memento.Serialize());
        }
        
        File.WriteAllLines(filePath, serializedStates);
        Console.WriteLine($"历史记录已保存到 {filePath}");
    }
    
    // 从文件加载历史记录
    public void LoadHistoryFromFile(string filePath)
    {
        if (!File.Exists(filePath))
        {
            Console.WriteLine($"历史记录文件 {filePath} 不存在");
            return;
        }
        
        _undoStack.Clear();
        _redoStack.Clear();
        
        string[] serializedStates = File.ReadAllLines(filePath);
        
        foreach (string serialized in serializedStates)
        {
            DocumentMemento memento = DocumentMemento.Deserialize(serialized);
            _undoStack.Push(memento);
        }
        
        if (_undoStack.Count > 0)
        {
            _document.RestoreFromMemento(_undoStack.Peek());
            Console.WriteLine("已从文件加载历史记录");
        }
        
        OnHistoryChanged();
    }
    
    // 显示历史记录
    public void DisplayHistory()
    {
        Console.WriteLine("\n=== 历史记录 ===");
        Console.WriteLine($"可撤销操作数: {_undoStack.Count - 1}"); // 减去初始状态
        Console.WriteLine($"可重做操作数: {_redoStack.Count}");
        
        if (_undoStack.Count > 0)
        {
            Console.WriteLine("\n撤销栈(最近 5 个状态):");
            int count = 0;
            foreach (var memento in _undoStack)
            {
                if (count++ >= 5) break;
                
                string content = memento.Text;
                if (content.Length > 30)
                {
                    content = content.Substring(0, 27) + "...";
                }
                
                Console.WriteLine($"- [{memento.SavedTime:HH:mm:ss}] {memento.Description} - '{content}'");
            }
        }
        
        if (_redoStack.Count > 0)
        {
            Console.WriteLine("\n重做栈(最近 5 个状态):");
            int count = 0;
            foreach (var memento in _redoStack)
            {
                if (count++ >= 5) break;
                
                string content = memento.Text;
                if (content.Length > 30)
                {
                    content = content.Substring(0, 27) + "...";
                }
                
                Console.WriteLine($"- [{memento.SavedTime:HH:mm:ss}] {memento.Description} - '{content}'");
            }
        }
    }
    
    protected virtual void OnHistoryChanged()
    {
        HistoryChanged?.Invoke(this, new HistoryChangedEventArgs
        {
            UndoCount = _undoStack.Count - 1, // 减去初始状态
            RedoCount = _redoStack.Count,
            CurrentState = _undoStack.Count > 0 ? _undoStack.Peek() : null
        });
    }
}

// 17. 历史变更事件参数
public class HistoryChangedEventArgs : EventArgs
{
    public int UndoCount { get; set; }
    public int RedoCount { get; set; }
    public DocumentMemento CurrentState { get; set; }
}

// 18. 文本编辑器 - 使用文档和历史管理器
public class AdvancedTextEditor
{
    private readonly TextDocument _document;
    private readonly DocumentHistoryManager _historyManager;
    
    public AdvancedTextEditor()
    {
        _document = new TextDocument();
        _historyManager = new DocumentHistoryManager(_document);
        
        // 订阅历史变更事件
        _historyManager.HistoryChanged += HistoryManager_HistoryChanged;
    }
    
    private void HistoryManager_HistoryChanged(object sender, HistoryChangedEventArgs e)
    {
        // 可以更新UI状态,如启用/禁用撤销重做按钮
        Console.WriteLine($"历史状态变更: 可撤销 {e.UndoCount}, 可重做 {e.RedoCount}");
    }
    
    // 编辑操作
    public void InsertText(string text)
    {
        _document.InsertText(text);
    }
    
    public void DeleteText(int length)
    {
        _document.DeleteText(length);
    }
    
    public void ReplaceText(int position, int length, string newText)
    {
        _document.ReplaceText(position, length, newText);
    }
    
    public void MoveCursor(int position)
    {
        _document.MoveCursor(position);
    }
    
    public void SelectText(int startPosition, int endPosition)
    {
        _document.SelectText(startPosition, endPosition);
    }
    
    public void ApplyStyle(bool isBold, bool isItalic, bool isUnderlined, string textColor = "Black")
    {
        var style = new TextStyle
        {
            IsBold = isBold,
            IsItalic = isItalic,
            IsUnderlined = isUnderlined,
            TextColor = textColor
        };
        
        _document.ApplyStyle(style);
    }
    
    // 历史操作
    public void Undo()
    {
        _historyManager.Undo();
    }
    
    public void Redo()
    {
        _historyManager.Redo();
    }
    
    public void SaveState(string description = "手动保存")
    {
        _historyManager.SaveState(description);
    }
    
    // 文件操作
    public void SaveToFile(string filePath)
    {
        _document.SaveToFile(filePath);
    }
    
    public void LoadFromFile(string filePath)
    {
        _document.LoadFromFile(filePath);
    }
    
    public void SaveHistoryToFile(string filePath)
    {
        _historyManager.SaveHistoryToFile(filePath);
    }
    
    public void LoadHistoryFromFile(string filePath)
    {
        _historyManager.LoadHistoryFromFile(filePath);
    }
    
    // 分组操作示例 - 格式化段落
    public void FormatParagraph(int startPosition, int length)
    {
        var group = new OperationGroup("格式化段落");
        
        // 创建一系列操作
        var selectOp = new SelectTextOperation(startPosition, startPosition + length);
        var styleOp = new ApplyStyleOperation(startPosition, length, new TextStyle 
        { 
            FontSize = 14, 
            IsBold = true 
        });
        
        // 添加到组
        group.AddOperation(selectOp);
        group.AddOperation(styleOp);
        
        // 执行操作组
        _document.ExecuteOperation(group);
    }
    
    // 显示当前状态
    public void DisplayCurrentState()
    {
        _document.Display();
        _historyManager.DisplayHistory();
    }
}

// 19. 客户端代码
public class Client
{
    public static void Main()
    {
        // 创建高级文本编辑器
        AdvancedTextEditor editor = new AdvancedTextEditor();
        
        // 执行一系列编辑操作
        Console.WriteLine("=== 初始状态 ===");
        editor.DisplayCurrentState();
        
        // 插入文本
        editor.InsertText("Hello, World!");
        Console.WriteLine("\n=== 插入 'Hello, World!' 后 ===");
        editor.DisplayCurrentState();
        
        // 移动光标
        editor.MoveCursor(7);
        Console.WriteLine("\n=== 移动光标到位置 7 后 ===");
        editor.DisplayCurrentState();
        
        // 插入更多文本
        editor.InsertText("beautiful ");
        Console.WriteLine("\n=== 插入 'beautiful ' 后 ===");
        editor.DisplayCurrentState();
        
        // 选择文本并应用样式
        editor.SelectText(0, 16);
        editor.ApplyStyle(true, false, false, "Blue");
        Console.WriteLine("\n=== 对前16个字符应用样式后 ===");
        editor.DisplayCurrentState();
        
        // 撤销操作
        editor.Undo();
        Console.WriteLine("\n=== 撤销后 ===");
        editor.DisplayCurrentState();
        
        // 再次撤销
        editor.Undo();
        Console.WriteLine("\n=== 再次撤销后 ===");
        editor.DisplayCurrentState();
        
        // 重做操作
        editor.Redo();
        Console.WriteLine("\n=== 重做后 ===");
        editor.DisplayCurrentState();
        
        // 使用操作组
        editor.FormatParagraph(0, 16);
        Console.WriteLine("\n=== 使用操作组格式化段落后 ===");
        editor.DisplayCurrentState();
        
        // 保存状态
        editor.SaveState("用户手动保存");
        Console.WriteLine("\n=== 保存状态后 ===");
        editor.DisplayCurrentState();
        
        // 保存文件
        string tempFilePath = Path.Combine(Path.GetTempPath(), "document.txt");
        editor.SaveToFile(tempFilePath);
        Console.WriteLine($"\n=== 文档已保存到 {tempFilePath} ===");
        
        // 保存历史
        string historyFilePath = Path.Combine(Path.GetTempPath(), "document_history.json");
        editor.SaveHistoryToFile(historyFilePath);
        Console.WriteLine($"=== 历史记录已保存到 {historyFilePath} ===");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229

业务场景结合:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;

// 多步骤表单系统 - 使用备忘录模式实现自动保存和表单状态恢复

// 1. 表单字段基类
public abstract class FormField
{
    public string Id { get; }
    public string Label { get; set; }
    public bool IsRequired { get; set; }
    public string ValidationError { get; protected set; }
    public bool IsValid { get; protected set; } = true;
    
    protected FormField(string id, string label, bool isRequired = false)
    {
        Id = id;
        Label = label;
        IsRequired = isRequired;
    }
    
    public abstract object GetValue();
    public abstract void SetValue(object value);
    public abstract bool Validate();
    public abstract FormField Clone();
    public abstract string GetDisplayText();
}

// 2. 具体字段类型 - 文本字段
public class TextField : FormField
{
    public string Value { get; set; }
    public int MaxLength { get; set; } = 100;
    public string Placeholder { get; set; }
    public bool IsMultiline { get; set; }
    
    public TextField(string id, string label, bool isRequired = false)
        : base(id, label, isRequired)
    {
    }
    
    public override object GetValue()
    {
        return Value;
    }
    
    public override void SetValue(object value)
    {
        Value = value?.ToString();
    }
    
    public override bool Validate()
    {
        if (IsRequired && string.IsNullOrWhiteSpace(Value))
        {
            ValidationError = $"{Label} 是必填项";
            IsValid = false;
            return false;
        }
        
        if (Value != null && Value.Length > MaxLength)
        {
            ValidationError = $"{Label} 不能超过 {MaxLength} 个字符";
            IsValid = false;
            return false;
        }
        
        ValidationError = null;
        IsValid = true;
        return true;
    }
    
    public override FormField Clone()
    {
        return new TextField(Id, Label, IsRequired)
        {
            Value = Value,
            MaxLength = MaxLength,
            Placeholder = Placeholder,
            IsMultiline = IsMultiline,
            ValidationError = ValidationError,
            IsValid = IsValid
        };
    }
    
    public override string GetDisplayText()
    {
        return Value ?? "";
    }
}

// 3. 具体字段类型 - 数字字段
public class NumberField : FormField
{
    public double? Value { get; set; }
    public double? MinValue { get; set; }
    public double? MaxValue { get; set; }
    
    public NumberField(string id, string label, bool isRequired = false)
        : base(id, label, isRequired)
    {
    }
    
    public override object GetValue()
    {
        return Value;
    }
    
    public override void SetValue(object value)
    {
        if (value == null)
        {
            Value = null;
            return;
        }
        
        if (value is double doubleValue)
        {
            Value = doubleValue;
        }
        else if (double.TryParse(value.ToString(), out double parsedValue))
        {
            Value = parsedValue;
        }
    }
    
    public override bool Validate()
    {
        if (IsRequired && Value == null)
        {
            ValidationError = $"{Label} 是必填项";
            IsValid = false;
            return false;
        }
        
        if (Value.HasValue)
        {
            if (MinValue.HasValue && Value < MinValue)
            {
                ValidationError = $"{Label} 不能小于 {MinValue}";
                IsValid = false;
                return false;
            }
            
            if (MaxValue.HasValue && Value > MaxValue)
            {
                ValidationError = $"{Label} 不能大于 {MaxValue}";
                IsValid = false;
                return false;
            }
        }
        
        ValidationError = null;
        IsValid = true;
        return true;
    }
    
    public override FormField Clone()
    {
        return new NumberField(Id, Label, IsRequired)
        {
            Value = Value,
            MinValue = MinValue,
            MaxValue = MaxValue,
            ValidationError = ValidationError,
            IsValid = IsValid
        };
    }
    
    public override string GetDisplayText()
    {
        return Value?.ToString() ?? "";
    }
}

// 4. 具体字段类型 - 日期字段
public class DateField : FormField
{
    public DateTime? Value { get; set; }
    public DateTime? MinDate { get; set; }
    public DateTime? MaxDate { get; set; }
    
    public DateField(string id, string label, bool isRequired = false)
        : base(id, label, isRequired)
    {
    }
    
    public override object GetValue()
    {
        return Value;
    }
    
    public override void SetValue(object value)
    {
        if (value == null)
        {
            Value = null;
            return;
        }
        
        if (value is DateTime dateValue)
        {
            Value = dateValue;
        }
        else if (DateTime.TryParse(value.ToString(), out DateTime parsedValue))
        {
            Value = parsedValue;
        }
    }
    
    public override bool Validate()
    {
        if (IsRequired && Value == null)
        {
            ValidationError = $"{Label} 是必填项";
            IsValid = false;
            return false;
        }
        
        if (Value.HasValue)
        {
            if (MinDate.HasValue && Value < MinDate)
            {
                ValidationError = $"{Label} 不能早于 {MinDate:yyyy-MM-dd}";
                IsValid = false;
                return false;
            }
            
            if (MaxDate.HasValue && Value > MaxDate)
            {
                ValidationError = $"{Label} 不能晚于 {MaxDate:yyyy-MM-dd}";
                IsValid = false;
                return false;
            }
        }
        
        ValidationError = null;
        IsValid = true;
        return true;
    }
    
    public override FormField Clone()
    {
        return new DateField(Id, Label, IsRequired)
        {
            Value = Value,
            MinDate = MinDate,
            MaxDate = MaxDate,
            ValidationError = ValidationError,
            IsValid = IsValid
        };
    }
    
    public override string GetDisplayText()
    {
        return Value?.ToString("yyyy-MM-dd") ?? "";
    }
}

// 5. 具体字段类型 - 选择字段
public class SelectField : FormField
{
    public string Value { get; set; }
    public List<SelectOption> Options { get; set; } = new List<SelectOption>();
    
    public SelectField(string id, string label, bool isRequired = false)
        : base(id, label, isRequired)
    {
    }
    
    public override object GetValue()
    {
        return Value;
    }
    
    public override void SetValue(object value)
    {
        Value = value?.ToString();
    }
    
    public void AddOption(string value, string text)
    {
        Options.Add(new SelectOption { Value = value, Text = text });
    }
    
    public override bool Validate()
    {
        if (IsRequired && string.IsNullOrWhiteSpace(Value))
        {
            ValidationError = $"{Label} 是必填项";
            IsValid = false;
            return false;
        }
        
        if (!string.IsNullOrEmpty(Value) && !Options.Any(o => o.Value == Value))
        {
            ValidationError = $"{Label} 的值不在有效选项中";
            IsValid = false;
            return false;
        }
        
        ValidationError = null;
        IsValid = true;
        return true;
    }
    
    public override FormField Clone()
    {
        var clone = new SelectField(Id, Label, IsRequired)
        {
            Value = Value,
            ValidationError = ValidationError,
            IsValid = IsValid
        };
        
        foreach (var option in Options)
        {
            clone.Options.Add(new SelectOption
            {
                Value = option.Value,
                Text = option.Text
            });
        }
        
        return clone;
    }
    
    public override string GetDisplayText()
    {
        if (string.IsNullOrEmpty(Value))
            return "";
            
        var option = Options.FirstOrDefault(o => o.Value == Value);
        return option?.Text ?? Value;
    }
    
    public class SelectOption
    {
        public string Value { get; set; }
        public string Text { get; set; }
    }
}

// 6. 具体字段类型 - 复选框字段
public class CheckboxField : FormField
{
    public bool Value { get; set; }
    
    public CheckboxField(string id, string label, bool isRequired = false)
        : base(id, label, isRequired)
    {
    }
    
    public override object GetValue()
    {
        return Value;
    }
    
    public override void SetValue(object value)
    {
        if (value == null)
        {
            Value = false;
            return;
        }
        
        if (value is bool boolValue)
        {
            Value = boolValue;
        }
        else if (bool.TryParse(value.ToString(), out bool parsedValue))
        {
            Value = parsedValue;
        }
    }
    
    public override bool Validate()
    {
        if (IsRequired && !Value)
        {
            ValidationError = $"请勾选 {Label}";
            IsValid = false;
            return false;
        }
        
        ValidationError = null;
        IsValid = true;
        return true;
    }
    
    public override FormField Clone()
    {
        return new CheckboxField(Id, Label, IsRequired)
        {
            Value = Value,
            ValidationError = ValidationError,
            IsValid = IsValid
        };
    }
    
    public override string GetDisplayText()
    {
        return Value ? "是" : "否";
    }
}

// 7. 表单步骤类
public class FormStep
{
    public string Id { get; }
    public string Title { get; set; }
    public string Description { get; set; }
    public List<FormField> Fields { get; } = new List<FormField>();
    
    public FormStep(string id, string title, string description = "")
    {
        Id = id;
        Title = title;
        Description = description;
    }
    
    public void AddField(FormField field)
    {
        Fields.Add(field);
    }
    
    public FormField GetField(string id)
    {
        return Fields.FirstOrDefault(f => f.Id == id);
    }
    
    public bool Validate()
    {
        bool isValid = true;
        
        foreach (var field in Fields)
        {
            if (!field.Validate())
            {
                isValid = false;
            }
        }
        
        return isValid;
    }
    
    public FormStep Clone()
    {
        var clone = new FormStep(Id, Title, Description);
        
        foreach (var field in Fields)
        {
            clone.AddField(field.Clone());
        }
        
        return clone;
    }
}

// 8. 表单状态备忘录
public class FormMemento
{
    public string FormId { get; }
    public List<FormStepState> Steps { get; } = new List<FormStepState>();
    public int CurrentStepIndex { get; set; }
    public DateTime SaveTime { get; }
    public string UserId { get; }
    
    public FormMemento(string formId, int currentStepIndex, string userId)
    {
        FormId = formId;
        CurrentStepIndex = currentStepIndex;
        SaveTime = DateTime.Now;
        UserId = userId;
    }
    
    public class FormStepState
    {
        public string StepId { get; set; }
        public List<FormFieldState> Fields { get; } = new List<FormFieldState>();
    }
    
    public class FormFieldState
    {
        public string FieldId { get; set; }
        public object Value { get; set; }
    }
    
    // 序列化方法
    public string Serialize()
    {
        return JsonSerializer.Serialize(this);
    }
    
    // 反序列化方法
    public static FormMemento Deserialize(string json)
    {
        return JsonSerializer.Deserialize<FormMemento>(json);
    }
}

// 9. 表单管理器 - 发起者
public class MultiStepForm
{
    private readonly List<FormStep> _steps = new List<FormStep>();
    private int _currentStepIndex = 0;
    private string _formId;
    private string _title;
    private string _userId;
    private DateTime _createdTime;
    private DateTime _lastSaveTime;
    private readonly Timer _autoSaveTimer;
    private readonly int _autoSaveInterval = 30000; // 30秒
    private bool _isDirty = false;
    
    public event EventHandler<FormChangedEventArgs> FormChanged;
    public event EventHandler<FormSavedEventArgs> FormSaved;
    
    public string FormId => _formId;
    public string Title => _title;
    public string UserId => _userId;
    public DateTime CreatedTime => _createdTime;
    public DateTime LastSaveTime => _lastSaveTime;
    public FormStep CurrentStep => _currentStepIndex < _steps.Count ? _steps[_currentStepIndex] : null;
    public int CurrentStepIndex => _currentStepIndex;
    public int TotalSteps => _steps.Count;
    public bool IsDirty => _isDirty;
    
    public MultiStepForm(string formId, string title, string userId)
    {
        _formId = formId;
        _title = title;
        _userId = userId;
        _createdTime = DateTime.Now;
        _lastSaveTime = DateTime.MinValue;
        
        // 设置自动保存计时器
        _autoSaveTimer = new Timer(AutoSave, null, _autoSaveInterval, _autoSaveInterval);
    }
    
    // 自动保存回调
    private void AutoSave(object state)
    {
        if (_isDirty)
        {
            var memento = CreateMemento("自动保存");
            OnFormSaved(new FormSavedEventArgs
            {
                Memento = memento,
                SaveTime = DateTime.Now,
                IsAutoSave = true
            });
            
            _isDirty = false;
            _lastSaveTime = DateTime.Now;
        }
    }
    
    public void AddStep(FormStep step)
    {
        _steps.Add(step);
    }
    
    public bool GoToNextStep()
    {
        // 验证当前步骤
        if (CurrentStep != null && !CurrentStep.Validate())
        {
            return false;
        }
        
        if (_currentStepIndex < _steps.Count - 1)
        {
            _currentStepIndex++;
            OnFormChanged(new FormChangedEventArgs { ChangeType = FormChangeType.StepChanged });
            return true;
        }
        
        return false;
    }
    
    public bool GoToPreviousStep()
    {
        if (_currentStepIndex > 0)
        {
            _currentStepIndex--;
            OnFormChanged(new FormChangedEventArgs { ChangeType = FormChangeType.StepChanged });
            return true;
        }
        
        return false;
    }
    
    public bool GoToStep(int stepIndex)
    {
        if (stepIndex >= 0 && stepIndex < _steps.Count)
        {
            _currentStepIndex = stepIndex;
            OnFormChanged(new FormChangedEventArgs { ChangeType = FormChangeType.StepChanged });
            return true;
        }
        
        return false;
    }
    
    public bool GoToStep(string stepId)
    {
        int index = _steps.FindIndex(s => s.Id == stepId);
        return GoToStep(index);
    }
    
    public FormField GetField(string fieldId)
    {
        foreach (var step in _steps)
        {
            var field = step.GetField(fieldId);
            if (field != null)
                return field;
        }
        
        return null;
    }
    
    public void SetFieldValue(string fieldId, object value)
    {
        var field = GetField(fieldId);
        if (field != null)
        {
            field.SetValue(value);
            _isDirty = true;
            OnFormChanged(new FormChangedEventArgs 
            { 
                ChangeType = FormChangeType.FieldValueChanged,
                FieldId = fieldId
            });
        }
    }
    
    public bool ValidateCurrentStep()
    {
        if (CurrentStep == null)
            return false;
            
        bool result = CurrentStep.Validate();
        OnFormChanged(new FormChangedEventArgs { ChangeType = FormChangeType.Validated });
        return result;
    }
    
    public bool ValidateAllSteps()
    {
        bool isValid = true;
        
        foreach (var step in _steps)
        {
            if (!step.Validate())
            {
                isValid = false;
            }
        }
        
        OnFormChanged(new FormChangedEventArgs { ChangeType = FormChangeType.Validated });
        return isValid;
    }
    
    // 创建备忘录
    public FormMemento CreateMemento(string reason = "手动保存")
    {
        var memento = new FormMemento(_formId, _currentStepIndex, _userId);
        
        foreach (var step in _steps)
        {
            var stepState = new FormMemento.FormStepState
            {
                StepId = step.Id
            };
            
            foreach (var field in step.Fields)
            {
                stepState.Fields.Add(new FormMemento.FormFieldState
                {
                    FieldId = field.Id,
                    Value = field.GetValue()
                });
            }
            
            memento.Steps.Add(stepState);
        }
        
        return memento;
    }
    
    // 从备忘录恢复
    public void RestoreFromMemento(FormMemento memento)
    {
        if (memento.FormId != _formId)
        {
            throw new ArgumentException("备忘录与表单不匹配");
        }
        
        foreach (var stepState in memento.Steps)
        {
            var step = _steps.FirstOrDefault(s => s.Id == stepState.StepId);
            if (step != null)
            {
                foreach (var fieldState in stepState.Fields)
                {
                    var field = step.GetField(fieldState.FieldId);
                    if (field != null)
                    {
                        field.SetValue(fieldState.Value);
                    }
                }
            }
        }
        
        _currentStepIndex = Math.Min(memento.CurrentStepIndex, _steps.Count - 1);
        _lastSaveTime = memento.SaveTime;
        _isDirty = false;
        
        OnFormChanged(new FormChangedEventArgs { ChangeType = FormChangeType.Restored });
    }
    
    // 手动保存
    public FormMemento Save(string reason = "手动保存")
    {
        var memento = CreateMemento(reason);
        
        _isDirty = false;
        _lastSaveTime = DateTime.Now;
        
        OnFormSaved(new FormSavedEventArgs
        {
            Memento = memento,
            SaveTime = _lastSaveTime,
            IsAutoSave = false
        });
        
        return memento;
    }
    
    // 获取表单摘要数据
    public Dictionary<string, string> GetSummaryData()
    {
        var summary = new Dictionary<string, string>();
        
        foreach (var step in _steps)
        {
            foreach (var field in step.Fields)
            {
                summary[field.Label] = field.GetDisplayText();
            }
        }
        
        return summary;
    }
    
    // 显示表单当前状态
    public void DisplayCurrentState()
    {
        Console.WriteLine($"\n=== {_title} ===");
        Console.WriteLine($"步骤 {_currentStepIndex + 1}/{_steps.Count}: {CurrentStep?.Title}");
        Console.WriteLine(CurrentStep?.Description);
        Console.WriteLine();
        
        if (CurrentStep != null)
        {
            foreach (var field in CurrentStep.Fields)
            {
                string valueText = field.GetDisplayText();
                string requiredMark = field.IsRequired ? "*" : "";
                string validationError = field.IsValid ? "" : $" - 错误: {field.ValidationError}";
                
                Console.WriteLine($"{field.Label}{requiredMark}: {valueText}{validationError}");
            }
        }
        
        Console.WriteLine();
        Console.WriteLine($"上次保存: {(_lastSaveTime > DateTime.MinValue ? _lastSaveTime.ToString("yyyy-MM-dd HH:mm:ss") : "从未保存")}");
        Console.WriteLine($"状态: {(_isDirty ? "已修改" : "未修改")}");
    }
    
    // 析构函数 - 清理定时器
    ~MultiStepForm()
    {
        _autoSaveTimer?.Dispose();
    }
    
    // 事件触发方法
    protected virtual void OnFormChanged(FormChangedEventArgs e)
    {
        FormChanged?.Invoke(this, e);
    }
    
    protected virtual void OnFormSaved(FormSavedEventArgs e)
    {
        FormSaved?.Invoke(this, e);
    }
}

// 10. 表单事件参数
public class FormChangedEventArgs : EventArgs
{
    public FormChangeType ChangeType { get; set; }
    public string FieldId { get; set; }
}

public class FormSavedEventArgs : EventArgs
{
    public FormMemento Memento { get; set; }
    public DateTime SaveTime { get; set; }
    public bool IsAutoSave { get; set; }
}

// 11. 表单变更类型枚举
public enum FormChangeType
{
    FieldValueChanged,
    StepChanged,
    Validated,
    Restored
}

// 12. 表单备忘录管理器 - 负责人
public class FormMementoManager
{
    private readonly Dictionary<string, List<FormMemento>> _mementos = new Dictionary<string, List<FormMemento>>();
    private readonly int _maxHistoryPerForm;
    private readonly ILogger<FormMementoManager> _logger;
    
    public FormMementoManager(ILogger<FormMementoManager> logger, int maxHistoryPerForm = 10)
    {
        _logger = logger;
        _maxHistoryPerForm = maxHistoryPerForm;
    }
    
    // 保存备忘录
    public void SaveMemento(FormMemento memento)
    {
        string key = GetKey(memento.FormId, memento.UserId);
        
        if (!_mementos.ContainsKey(key))
        {
            _mementos[key] = new List<FormMemento>();
        }
        
        _mementos[key].Add(memento);
        
        // 限制历史记录数量
        if (_mementos[key].Count > _maxHistoryPerForm)
        {
            _mementos[key].RemoveAt(0);
        }
        
        _logger.LogInformation("已保存表单 {FormId} 的状态,用户 {UserId}, 时间 {SaveTime}", 
            memento.FormId, memento.UserId, memento.SaveTime);
            
        // 持久化到文件
        SaveToFile(memento);
    }
    
    // 获取最新备忘录
    public FormMemento GetLatestMemento(string formId, string userId)
    {
        string key = GetKey(formId, userId);
        
        if (_mementos.TryGetValue(key, out var history) && history.Count > 0)
        {
            return history.Last();
        }
        
        // 尝试从文件加载
        var memento = LoadFromFile(formId, userId);
        if (memento != null)
        {
            if (!_mementos.ContainsKey(key))
            {
                _mementos[key] = new List<FormMemento>();
            }
            
            _mementos[key].Add(memento);
            return memento;
        }
        
        return null;
    }
    
    // 获取历史备忘录
    public List<FormMemento> GetHistory(string formId, string userId)
    {
        string key = GetKey(formId, userId);
        
        if (_mementos.TryGetValue(key, out var history))
        {
            return new List<FormMemento>(history);
        }
        
        return new List<FormMemento>();
    }
    
    // 从指定时间点恢复
    public FormMemento GetMementoByTime(string formId, string userId, DateTime targetTime)
    {
        var history = GetHistory(formId, userId);
        
        // 找到最接近但不晚于目标时间的备忘录
        return history
            .Where(m => m.SaveTime <= targetTime)
            .OrderByDescending(m => m.SaveTime)
            .FirstOrDefault();
    }
    
    // 清除历史
    public void ClearHistory(string formId, string userId)
    {
        string key = GetKey(formId, userId);
        
        if (_mementos.ContainsKey(key))
        {
            _mementos.Remove(key);
            _logger.LogInformation("已清除表单 {FormId} 的历史记录,用户 {UserId}", formId, userId);
            
            // 删除文件
            string filePath = GetFilePath(formId, userId);
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
        }
    }
    
    // 将备忘录保存到文件
    private void SaveToFile(FormMemento memento)
    {
        try
        {
            string filePath = GetFilePath(memento.FormId, memento.UserId);
            Directory.CreateDirectory(Path.GetDirectoryName(filePath));
            
            string json = memento.Serialize();
            File.WriteAllText(filePath, json);
            
            _logger.LogDebug("已将表单 {FormId} 的状态保存到文件", memento.FormId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "保存表单状态到文件时出错");
        }
    }
    
    // 从文件加载备忘录
    private FormMemento LoadFromFile(string formId, string userId)
    {
        try
        {
            string filePath = GetFilePath(formId, userId);
            
            if (File.Exists(filePath))
            {
                string json = File.ReadAllText(filePath);
                var memento = FormMemento.Deserialize(json);
                
                _logger.LogDebug("已从文件加载表单 {FormId} 的状态", formId);
                return memento;
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "从文件加载表单状态时出错");
        }
        
        return null;
    }
    
    // 获取表单和用户的组合键
    private string GetKey(string formId, string userId)
    {
        return $"{formId}:{userId}";
    }
    
    // 获取文件路径
    private string GetFilePath(string formId, string userId)
    {
        string baseDir = Path.Combine(Path.GetTempPath(), "FormStates");
        return Path.Combine(baseDir, $"{formId}_{userId}.json");
    }
}

// 13. 表单系统 - 组合使用表单和备忘录管理器
public class FormSystem
{
    private readonly Dictionary<string, MultiStepForm> _activeForms = new Dictionary<string, MultiStepForm>();
    private readonly FormMementoManager _mementoManager;
    private readonly ILogger<FormSystem> _logger;
    
    public FormSystem(FormMementoManager mementoManager, ILogger<FormSystem> logger)
    {
        _mementoManager = mementoManager;
        _logger = logger;
    }
    
    // 创建新表单
    public MultiStepForm CreateForm(string formId, string title, string userId)
    {
        if (_activeForms.ContainsKey(formId))
        {
            throw new ArgumentException($"表单ID {formId} 已存在");
        }
        
        var form = new MultiStepForm(formId, title, userId);
        
        // 订阅表单事件
        form.FormSaved += Form_Saved;
        
        _activeForms[formId] = form;
        _logger.LogInformation("已创建新表单 {FormId} '{Title}' 给用户 {UserId}", formId, title, userId);
        
        return form;
    }
    
    // 获取表单
    public MultiStepForm GetForm(string formId)
    {
        if (_activeForms.TryGetValue(formId, out var form))
        {
            return form;
        }
        
        return null;
    }
    
    // 加载表单,如果有保存的状态则恢复
    public MultiStepForm LoadForm(string formId, string title, string userId)
    {
        // 检查是否已经加载
        if (_activeForms.TryGetValue(formId, out var existingForm))
        {
            return existingForm;
        }
        
        // 创建新表单
        var form = CreateForm(formId, title, userId);
        
        // 查找保存的状态
        var memento = _mementoManager.GetLatestMemento(formId, userId);
        
        if (memento != null)
        {
            form.RestoreFromMemento(memento);
            _logger.LogInformation("已恢复表单 {FormId} 的保存状态,保存时间: {SaveTime}", 
                formId, memento.SaveTime);
        }
        
        return form;
    }
    
    // 关闭表单
    public void CloseForm(string formId)
    {
        if (_activeForms.TryGetValue(formId, out var form))
        {
            // 取消订阅事件
            form.FormSaved -= Form_Saved;
            
            // 如果有未保存的更改,自动保存
            if (form.IsDirty)
            {
                var memento = form.Save("关闭表单时自动保存");
                _mementoManager.SaveMemento(memento);
            }
            
            _activeForms.Remove(formId);
            _logger.LogInformation("已关闭表单 {FormId}", formId);
        }
    }
    
    // 提交表单
    public bool SubmitForm(string formId)
    {
        if (_activeForms.TryGetValue(formId, out var form))
        {
            // 验证所有步骤
            if (!form.ValidateAllSteps())
            {
                _logger.LogWarning("表单 {FormId} 验证失败,无法提交", formId);
                return false;
            }
            
            // 创建最终备忘录
            var memento = form.Save("表单提交");
            _mementoManager.SaveMemento(memento);
            
            // 处理表单数据(实际应用中可能会保存到数据库)
            var formData = form.GetSummaryData();
            _logger.LogInformation("表单 {FormId} 已成功提交,共 {FieldCount} 个字段", 
                formId, formData.Count);
                
            // 关闭表单
            CloseForm(formId);
            
            return true;
        }
        
        _logger.LogWarning("找不到表单 {FormId},无法提交", formId);
        return false;
    }
    
    // 清除表单历史
    public void ClearFormHistory(string formId, string userId)
    {
        _mementoManager.ClearHistory(formId, userId);
        _logger.LogInformation("已清除表单 {FormId} 的历史记录", formId);
    }
    
    // 表单保存事件处理
    private void Form_Saved(object sender, FormSavedEventArgs e)
    {
        if (sender is MultiStepForm form)
        {
            _mementoManager.SaveMemento(e.Memento);
        }
    }
    
    // 获取表单历史
    public List<FormMemento> GetFormHistory(string formId, string userId)
    {
        return _mementoManager.GetHistory(formId, userId);
    }
    
    // 从特定状态恢复表单
    public bool RestoreFormFromHistory(string formId, string userId, DateTime timestamp)
    {
        if (_activeForms.TryGetValue(formId, out var form))
        {
            var memento = _mementoManager.GetMementoByTime(formId, userId, timestamp);
            
            if (memento != null)
            {
                form.RestoreFromMemento(memento);
                _logger.LogInformation("已将表单 {FormId} 恢复到 {Timestamp} 的状态", 
                    formId, timestamp);
                return true;
            }
            
            _logger.LogWarning("找不到表单 {FormId} 在 {Timestamp} 的状态", formId, timestamp);
            return false;
        }
        
        _logger.LogWarning("找不到表单 {FormId},无法恢复", formId);
        return false;
    }
}

// 14. 表单模板创建器 - 简化创建常见表单
public class FormTemplateBuilder
{
    // 创建求职申请表
    public static MultiStepForm CreateJobApplicationForm(string userId)
    {
        string formId = $"job_application_{Guid.NewGuid():N}";
        var form = new MultiStepForm(formId, "求职申请表", userId);
        
        // 步骤1:个人信息
        var personalInfoStep = new FormStep("personal_info", "个人信息", "请填写您的基本个人信息");
        
        personalInfoStep.AddField(new TextField("name", "姓名", true) { MaxLength = 50 });
        personalInfoStep.AddField(new TextField("email", "电子邮箱", true) { MaxLength = 100 });
        personalInfoStep.AddField(new TextField("phone", "联系电话", true) { MaxLength = 20 });
        personalInfoStep.AddField(new DateField("dob", "出生日期", true) 
        { 
            MaxDate = DateTime.Now.AddYears(-18) // 必须年满18岁
        });
        personalInfoStep.AddField(new TextField("address", "联系地址", true) { MaxLength = 200, IsMultiline = true });
        
        form.AddStep(personalInfoStep);
        
        // 步骤2:教育背景
        var educationStep = new FormStep("education", "教育背景", "请填写您的最高学历信息");
        
        var educationLevelField = new SelectField("education_level", "最高学历", true);
        educationLevelField.AddOption("high_school", "高中");
        educationLevelField.AddOption("associate", "大专");
        educationLevelField.AddOption("bachelor", "本科");
        educationLevelField.AddOption("master", "硕士");
        educationLevelField.AddOption("phd", "博士");
        
        educationStep.AddField(educationLevelField);
        educationStep.AddField(new TextField("school", "学校名称", true) { MaxLength = 100 });
        educationStep.AddField(new TextField("major", "专业", true) { MaxLength = 100 });
        educationStep.AddField(new DateField("graduation_date", "毕业日期", true) 
        { 
            MaxDate = DateTime.Now.AddYears(5) // 允许未来5年内的毕业日期
        });
        educationStep.AddField(new NumberField("gpa", "GPA", false) { MinValue = 0, MaxValue = 4.0 });
        
        form.AddStep(educationStep);
        
        // 步骤3:工作经验
        var experienceStep = new FormStep("experience", "工作经验", "请填写您的最近一份工作经验");
        
        experienceStep.AddField(new TextField("company", "公司名称", false) { MaxLength = 100 });
        experienceStep.AddField(new TextField("position", "职位", false) { MaxLength = 100 });
        experienceStep.AddField(new DateField("start_date", "开始日期", false) 
        { 
            MaxDate = DateTime.Now // 不能是未来日期
        });
        experienceStep.AddField(new DateField("end_date", "结束日期", false) 
        { 
            MaxDate = DateTime.Now // 不能是未来日期
        });
        experienceStep.AddField(new CheckboxField("current_job", "这是我当前的工作", false));
        experienceStep.AddField(new TextField("responsibilities", "职责描述", false) 
        { 
            MaxLength = 500,
            IsMultiline = true 
        });
        
        form.AddStep(experienceStep);
        
        // 步骤4:技能和资格
        var skillsStep = new FormStep("skills", "技能和资格", "请填写您的技能和资格证书");
        
        skillsStep.AddField(new TextField("skills", "技能列表", true) 
        { 
            MaxLength = 300,
            IsMultiline = true,
            Placeholder = "请列出您掌握的技能,用逗号分隔" 
        });
        
        skillsStep.AddField(new TextField("certifications", "资格证书", false) 
        { 
            MaxLength = 300,
            IsMultiline = true 
        });
        
        skillsStep.AddField(new SelectField("language", "英语水平", true));
        ((SelectField)skillsStep.GetField("language")).AddOption("beginner", "初级");
        ((SelectField)skillsStep.GetField("language")).AddOption("intermediate", "中级");
        ((SelectField)skillsStep.GetField("language")).AddOption("advanced", "高级");
        ((SelectField)skillsStep.GetField("language")).AddOption("fluent", "流利");
        ((SelectField)skillsStep.GetField("language")).AddOption("native", "母语");
        
        form.AddStep(skillsStep);
        
        // 步骤5:附加信息
        var additionalStep = new FormStep("additional", "附加信息", "请提供其他相关信息");
        
        additionalStep.AddField(new NumberField("expected_salary", "期望薪资(元/月)", true) 
        { 
            MinValue = 1000 
        });
        
        additionalStep.AddField(new DateField("available_date", "可入职日期", true) 
        { 
            MinDate = DateTime.Now
        });
        
        additionalStep.AddField(new TextField("referral", "推荐人", false) { MaxLength = 100 });
        
        additionalStep.AddField(new TextField("additional_info", "其他信息", false) 
        { 
            MaxLength = 1000,
            IsMultiline = true,
            Placeholder = "请提供任何可能对您的申请有帮助的其他信息" 
        });
        
        additionalStep.AddField(new CheckboxField("terms", "我同意处理我的个人数据用于招聘目的", true));
        
        form.AddStep(additionalStep);
        
        return form;
    }
    
    // 创建客户反馈表
    public static MultiStepForm CreateFeedbackForm(string userId)
    {
        string formId = $"feedback_{Guid.NewGuid():N}";
        var form = new MultiStepForm(formId, "客户反馈表", userId);
        
        // 步骤1:客户信息
        var customerInfoStep = new FormStep("customer_info", "客户信息", "请提供您的基本信息");
        
        customerInfoStep.AddField(new TextField("name", "姓名", false) { MaxLength = 50 });
        customerInfoStep.AddField(new TextField("email", "电子邮箱", true) { MaxLength = 100 });
        customerInfoStep.AddField(new TextField("phone", "联系电话", false) { MaxLength = 20 });
        
        var customerTypeField = new SelectField("customer_type", "客户类型", true);
        customerTypeField.AddOption("new", "新客户");
        customerTypeField.AddOption("existing", "现有客户");
        customerTypeField.AddOption("former", "前客户");
        
        customerInfoStep.AddField(customerTypeField);
        
        form.AddStep(customerInfoStep);
        
        // 步骤2:产品评价
        var productFeedbackStep = new FormStep("product_feedback", "产品评价", "请评价我们的产品");
        
        var productField = new SelectField("product", "产品名称", true);
        productField.AddOption("product_a", "产品A");
        productField.AddOption("product_b", "产品B");
        productField.AddOption("product_c", "产品C");
        productField.AddOption("product_d", "产品D");
        
        productFeedbackStep.AddField(productField);
        
        var satisfactionField = new SelectField("satisfaction", "总体满意度", true);
        satisfactionField.AddOption("5", "非常满意");
        satisfactionField.AddOption("4", "满意");
        satisfactionField.AddOption("3", "一般");
        satisfactionField.AddOption("2", "不满意");
        satisfactionField.AddOption("1", "非常不满意");
        
        productFeedbackStep.AddField(satisfactionField);
        
        productFeedbackStep.AddField(new TextField("likes", "您最喜欢产品的哪些方面?", false) 
        { 
            MaxLength = 500,
            IsMultiline = true 
        });
        
        productFeedbackStep.AddField(new TextField("dislikes", "您认为产品哪些方面需要改进?", false) 
        { 
            MaxLength = 500,
            IsMultiline = true 
        });
        
        form.AddStep(productFeedbackStep);
        
        // 步骤3:服务评价
        var serviceFeedbackStep = new FormStep("service_feedback", "服务评价", "请评价我们的客户服务");
        
        var serviceField = new SelectField("service_satisfaction", "客户服务满意度", true);
        serviceField.AddOption("5", "非常满意");
        serviceField.AddOption("4", "满意");
        serviceField.AddOption("3", "一般");
        serviceField.AddOption("2", "不满意");
        serviceField.AddOption("1", "非常不满意");
        
        serviceFeedbackStep.AddField(serviceField);
        
        serviceFeedbackStep.AddField(new TextField("service_feedback", "您对我们的客户服务有何评价或建议?", false) 
        { 
            MaxLength = 500,
            IsMultiline = true 
        });
        
        serviceFeedbackStep.AddField(new CheckboxField("contacted", "您希望我们联系您跟进您的反馈吗?", false));
        
        form.AddStep(serviceFeedbackStep);
        
        // 步骤4:总结
        var summaryStep = new FormStep("summary", "总结", "请提供最后的总结性反馈");
        
        var recommendField = new SelectField("recommend", "您会向他人推荐我们的产品吗?", true);
        recommendField.AddOption("5", "一定会");
        recommendField.AddOption("4", "可能会");
        recommendField.AddOption("3", "不确定");
        recommendField.AddOption("2", "可能不会");
        recommendField.AddOption("1", "一定不会");
        
        summaryStep.AddField(recommendField);
        
        summaryStep.AddField(new TextField("comments", "其他意见或建议", false) 
        { 
            MaxLength = 1000,
            IsMultiline = true 
        });
        
        form.AddStep(summaryStep);
        
        return form;
    }
}

// 15. 表单控制台UI - 简化与用户交互
public class FormConsoleUI
{
    private readonly FormSystem _formSystem;
    private readonly ILogger<FormConsoleUI> _logger;
    private MultiStepForm _currentForm;
    
    public FormConsoleUI(FormSystem formSystem, ILogger<FormConsoleUI> logger)
    {
        _formSystem = formSystem;
        _logger = logger;
    }
    
    // 启动UI
    public void Start()
    {
        Console.WriteLine("=== 多步骤表单系统 ===");
        Console.WriteLine("请选择要填写的表单类型:");
        Console.WriteLine("1. 求职申请表");
        Console.WriteLine("2. 客户反馈表");
        Console.Write("请输入选择 (1 或 2): ");
        
        string choice = Console.ReadLine();
        string userId = "user_" + Guid.NewGuid().ToString("N").Substring(0, 8);
        
        switch (choice)
        {
            case "1":
                _currentForm = FormTemplateBuilder.CreateJobApplicationForm(userId);
                _formSystem.LoadForm(_currentForm.FormId, _currentForm.Title, userId);
                RunFormUI();
                break;
            case "2":
                _currentForm = FormTemplateBuilder.CreateFeedbackForm(userId);
                _formSystem.LoadForm(_currentForm.FormId, _currentForm.Title, userId);
                RunFormUI();
                break;
            default:
                Console.WriteLine("无效的选择");
                break;
        }
    }
    
    // 运行表单UI
    private void RunFormUI()
    {
        bool isRunning = true;
        
        while (isRunning)
        {
            Console.Clear();
            _currentForm.DisplayCurrentState();
            
            Console.WriteLine("\n命令: [n]下一步 [p]上一步 [f]填写字段 [s]保存 [h]历史 [q]退出");
            Console.Write("请输入命令: ");
            
            string command = Console.ReadLine().ToLower();
            
            switch (command)
            {
                case "n":
                    MoveToNextStep();
                    break;
                case "p":
                    MoveToPreviousStep();
                    break;
                case "f":
                    FillField();
                    break;
                case "s":
                    SaveForm();
                    break;
                case "h":
                    ShowHistory();
                    break;
                case "q":
                    isRunning = ConfirmExit();
                    break;
                default:
                    Console.WriteLine("无效的命令");
                    Console.WriteLine("按任意键继续...");
                    Console.ReadKey();
                    break;
            }
        }
        
        _formSystem.CloseForm(_currentForm.FormId);
    }
    
    // 填写字段
    private void FillField()
    {
        if (_currentForm.CurrentStep == null)
            return;
            
        Console.WriteLine("\n当前步骤的字段:");
        
        // 显示字段列表
        int index = 1;
        foreach (var field in _currentForm.CurrentStep.Fields)
        {
            Console.WriteLine($"{index++}. {field.Label}{(field.IsRequired ? " *" : "")}");
        }
        
        Console.Write("请选择要填写的字段编号: ");
        if (!int.TryParse(Console.ReadLine(), out int fieldIndex) || 
            fieldIndex < 1 || 
            fieldIndex > _currentForm.CurrentStep.Fields.Count)
        {
            Console.WriteLine("无效的字段编号");
            Console.WriteLine("按任意键继续...");
            Console.ReadKey();
            return;
        }
        
        // 获取选中的字段
        var field = _currentForm.CurrentStep.Fields[fieldIndex - 1];
        
        Console.WriteLine($"\n填写 {field.Label}:");
        if (field is CheckboxField)
        {
            Console.Write("是否选中 (y/n): ");
            string input = Console.ReadLine().ToLower();
            bool value = input == "y" || input == "yes" || input == "true";
            _currentForm.SetFieldValue(field.Id, value);
        }
        else if (field is SelectField selectField)
        {
            Console.WriteLine("可选项:");
            foreach (var option in selectField.Options)
            {
                Console.WriteLine($"- {option.Value}: {option.Text}");
            }
            
            Console.Write("请输入选择的值: ");
            string value = Console.ReadLine();
            _currentForm.SetFieldValue(field.Id, value);
        }
        else
        {
            Console.Write("请输入值: ");
            string value = Console.ReadLine();
            _currentForm.SetFieldValue(field.Id, value);
        }
    }
    
    // 移动到下一步
    private void MoveToNextStep()
    {
        if (!_currentForm.ValidateCurrentStep())
        {
            Console.WriteLine("\n当前步骤存在验证错误,无法继续");
            Console.WriteLine("按任意键继续...");
            Console.ReadKey();
            return;
        }
        
        if (!_currentForm.GoToNextStep())
        {
            if (_currentForm.CurrentStepIndex == _currentForm.TotalSteps - 1)
            {
                Console.WriteLine("\n这是最后一步,是否提交表单? (y/n)");
                string input = Console.ReadLine().ToLower();
                
                if (input == "y" || input == "yes")
                {
                    SubmitForm();
                }
            }
            else
            {
                Console.WriteLine("\n无法前进到下一步");
                Console.WriteLine("按任意键继续...");
                Console.ReadKey();
            }
        }
    }
    
    // 移动到上一步
    private void MoveToPreviousStep()
    {
        if (!_currentForm.GoToPreviousStep())
        {
            Console.WriteLine("\n已经是第一步,无法返回");
            Console.WriteLine("按任意键继续...");
            Console.ReadKey();
        }
    }
    
    // 保存表单
    private void SaveForm()
    {
        var memento = _currentForm.Save("用户手动保存");
        Console.WriteLine($"\n表单已保存,时间: {memento.SaveTime}");
        Console.WriteLine("按任意键继续...");
        Console.ReadKey();
    }
    
    // 提交表单
    private void SubmitForm()
    {
        if (_formSystem.SubmitForm(_currentForm.FormId))
        {
            Console.WriteLine("\n表单已成功提交,谢谢!");
            Console.WriteLine("按任意键退出...");
            Console.ReadKey();
            Environment.Exit(0);
        }
        else
        {
            Console.WriteLine("\n表单提交失败,请检查所有步骤是否填写正确");
            Console.WriteLine("按任意键继续...");
            Console.ReadKey();
        }
    }
    
    // 显示历史记录
    private void ShowHistory()
    {
        var history = _formSystem.GetFormHistory(_currentForm.FormId, _currentForm.UserId);
        
        Console.WriteLine("\n=== 表单历史记录 ===");
        
        if (history.Count == 0)
        {
            Console.WriteLine("没有保存的历史记录");
        }
        else
        {
            int index = 1;
            foreach (var memento in history)
            {
                Console.WriteLine($"{index++}. {memento.SaveTime}: 步骤 {memento.CurrentStepIndex + 1}");
            }
            
            Console.Write("\n选择一个历史记录恢复,或按Enter返回: ");
            if (int.TryParse(Console.ReadLine(), out int historyIndex) && 
                historyIndex >= 1 && 
                historyIndex <= history.Count)
            {
                var selectedMemento = history[historyIndex - 1];
                _currentForm.RestoreFromMemento(selectedMemento);
                Console.WriteLine($"已恢复到 {selectedMemento.SaveTime} 的状态");
            }
        }
        
        Console.WriteLine("按任意键继续...");
        Console.ReadKey();
    }
    
    // 确认退出
    private bool ConfirmExit()
    {
        if (_currentForm.IsDirty)
        {
            Console.WriteLine("\n表单有未保存的更改,是否保存后退出? (y/n)");
            string input = Console.ReadLine().ToLower();
            
            if (input == "y" || input == "yes")
            {
                SaveForm();
            }
        }
        
        Console.WriteLine("\n确认退出? (y/n)");
        string confirm = Console.ReadLine().ToLower();
        
        return confirm == "y" || confirm == "yes";
    }
}

// 16. 客户端代码
public class Client
{
    public static void Main()
    {
        // 设置依赖注入
        var services = new ServiceCollection();
        
        // 添加日志
        services.AddLogging(builder =>
        {
            builder.SetMinimumLevel(LogLevel.Information);
            builder.AddConsole();
        });
        
        // 注册服务
        services.AddSingleton<FormMementoManager>();
        services.AddSingleton<FormSystem>();
        services.AddSingleton<FormConsoleUI>();
        
        var serviceProvider = services.BuildServiceProvider();
        
        // 启动表单控制台UI
        var formUI = serviceProvider.GetRequiredService<FormConsoleUI>();
        formUI.Start();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
编辑 (opens new window)
#pattern
上次更新: 2026/03/11, 09:10:05
结构型
行为型二

← 结构型 行为型二→

最近更新
01
鉴权服务中心
03-11
02
聚合根
03-11
03
补充
02-06
更多文章>
Theme by Vdoing | Copyright © 2019-2026 moklgy's blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式