基于SOLID原则与设计模式重构C# InvoiceProcessor代码的最佳方案咨询
重构方案:基于SOLID与设计模式优化InvoiceProcessor
核心问题分析
原InvoiceProcessor类违反单一职责原则,同时承担了发票实例化、发票显示、加密逻辑、持久化存储多个职责,导致新增客户端规则或修改逻辑时需要大量修改该类,可维护性差。
重构步骤与设计模式应用
1. 拆分职责:提取独立类
把不同职责拆分为单独类,每个类只负责一项功能:
- 发票创建:用简单工厂模式封装实例化逻辑
- 显示逻辑:用策略模式封装不同客户端的显示规则
- 加密逻辑:用策略模式封装不同加密算法
- 存储逻辑:单独的存储类负责持久化
2. 具体重构代码
第一步:定义基础接口
首先确保Invoice基类/接口已存在(假设原代码中已有),新增以下接口:
// 加密策略接口 public interface IEncryptionStrategy { string Encrypt(string data); } // 显示策略接口 public interface IInvoiceDisplayStrategy { void Display(Invoice invoice); }
第二步:实现具体策略类
加密策略实现:
public class CaesarEncryption : IEncryptionStrategy { private const int Key = 4; public string Encrypt(string input) { var output = new StringBuilder(); foreach (char ch in input) { if (!char.IsLetter(ch)) { output.Append(ch); continue; } char baseChar = char.IsUpper(ch) ? 'A' : 'a'; output.Append((char)((((ch + Key) - baseChar) % 26) + baseChar)); } return output.ToString(); } } public class WeirdEncryption : IEncryptionStrategy { public string Encrypt(string input) { return input.Replace('A', '$').Replace('H', '#'); } }
显示策略实现:
public class DefaultInvoiceDisplay : IInvoiceDisplayStrategy { public void Display(Invoice invoice) { Console.WriteLine(invoice.Data); } } public class RedHighlightInvoiceDisplay : IInvoiceDisplayStrategy { public void Display(Invoice invoice) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(invoice.Data); Console.ResetColor(); // 重置颜色避免影响后续输出 } }
第三步:发票工厂类(封装实例化逻辑)
public class InvoiceFactory { public static Invoice CreateInvoice(int clientId) { return clientId switch { 0 => new SimpleInvoice(), 1 => new InvoiceWithHeader(), 2 => new InvoiceWithFooter(), 3 or 4 => new InvoiceWithHeaderFooter(), _ => throw new ArgumentException("无效客户端ID") }; } }
第四步:存储类(负责持久化)
public class InvoiceStorage { public void SaveInvoice(Invoice invoice, IEncryptionStrategy encryptionStrategy) { string encryptedData = encryptionStrategy.Encrypt(invoice.Data); File.WriteAllText("Invoice.txt", encryptedData); Console.WriteLine("发票数据已保存!"); } }
第五步:客户端策略映射类(集中管理规则)
把客户端ID和对应的策略映射集中管理,避免散落在代码中:
public class ClientStrategyProvider { public static IInvoiceDisplayStrategy GetDisplayStrategy(int clientId) { return clientId == 4 ? new RedHighlightInvoiceDisplay() : new DefaultInvoiceDisplay(); } public static IEncryptionStrategy GetEncryptionStrategy(int clientId) { return clientId switch { 0 or 1 => new CaesarEncryption(), 2 or 3 or 4 => new WeirdEncryption(), _ => throw new ArgumentException("无效客户端ID") }; } }
第六步:简化后的InvoiceProcessor
现在InvoiceProcessor只负责协调流程,不再承担具体业务逻辑:
using InvoiceApp.Invoices; namespace InvoiceApp { internal class InvoiceProcessor { private readonly InvoiceStorage _storage = new InvoiceStorage(); internal void Process(int client) { Console.WriteLine("正在处理发票..."); // 1. 创建发票 Invoice invoice = InvoiceFactory.CreateInvoice(client); invoice.CreateInvoice(); // 2. 获取对应策略 IInvoiceDisplayStrategy displayStrategy = ClientStrategyProvider.GetDisplayStrategy(client); IEncryptionStrategy encryptionStrategy = ClientStrategyProvider.GetEncryptionStrategy(client); // 3. 显示发票 displayStrategy.Display(invoice); // 4. 保存发票 _storage.SaveInvoice(invoice, encryptionStrategy); } } }
重构后的优势
- 符合单一职责:每个类只负责一项功能,比如
CaesarEncryption只处理凯撒加密,InvoiceFactory只负责创建发票 - 可扩展性强:新增客户端类型或加密算法时,只需新增对应策略类,修改映射规则即可,无需改动核心流程代码
- 可维护性提升:逻辑分散到各个职责类,定位问题和修改更高效
- 动态性增强:可以在运行时切换策略(比如根据配置动态选择加密方式)
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

