面向高级开发者的C#设计模式:从理论到代码
\n\n设计模式不仅仅是教科书中的抽象概念。对于经验丰富的C#开发者来说,它们是创建灵活、可扩展且易于维护的应用程序架构的工具。在本文中,我们将深入探讨三种常被基础课程忽略的强大模式:Visitor、Strategy和Command。您不仅会看到它们在C#中的实现,还会理解它们如何解决.NET生态系统中的实际问题。
\n\n1. Visitor(访问者)模式——处理对象层次结构
\n\nVisitor模式允许您在不修改现有类结构的情况下,向这些类添加新操作。当您拥有复杂的对象层次结构,并且希望根据其类型执行不同操作时,这尤其有用。
\n\n问题
\n假设您有一个包含TextDocument、Spreadsheet和Presentation类的文档管理系统。您需要添加导出为PDF、HTML和XML的功能。如果没有Visitor模式,您将不得不修改每个类,这违反了开闭原则(OCP)。
C#实现
\n// 1. 元素接口\npublic interface IElement\n{\n void Accept(IVisitor visitor);\n}\n\n// 2. 具体元素\npublic class TextDocument : IElement\n{\n public string Content { get; set; }\n public void Accept(IVisitor visitor) => visitor.Visit(this);\n}\n\npublic class Spreadsheet : IElement\n{\n public List<List<string>> Rows { get; set; }\n public void Accept(IVisitor visitor) => visitor.Visit(this);\n}\n\n// 3. 访问者接口\npublic interface IVisitor\n{\n void Visit(TextDocument doc);\n void Visit(Spreadsheet sheet);\n}\n\n// 4. 具体访问者——导出为HTML\npublic class HtmlExportVisitor : IVisitor\n{\n public void Visit(TextDocument doc)\n {\n Console.WriteLine($"<h1>{doc.Content}</h1>");\n }\n\n public void Visit(Spreadsheet sheet)\n {\n Console.WriteLine("<table>");\n foreach (var row in sheet.Rows)\n {\n Console.WriteLine("<tr><td>" + string.Join("</td><td>", row) + "</td></tr>");\n }\n Console.WriteLine("</table>");\n }\n}\n\n// 使用示例\nvar docs = new List<IElement> { new TextDocument { Content = "你好" }, new Spreadsheet { Rows = new List<List<string>> { new List<string> { "A", "B" } } } };\nvar visitor = new HtmlExportVisitor();\nforeach (var doc in docs) doc.Accept(visitor);\n\n优点:无需修改现有类即可轻松添加新操作。 缺点:如果元素层次结构频繁变化,Visitor模式会变得不便。
\n\n2. Strategy(策略)模式——动态切换算法
\n\nStrategy模式允许定义一系列算法,将每个算法封装起来,并使它们可以相互替换。这是避免庞大if-else或switch结构的经典方法。
问题
\n您需要实现一个运费计算系统。不同的配送方式:快递、邮政、自提。每种方式都有其独特的定价逻辑。
\n\nC#实现
\n// 1. 策略接口\npublic interface IShippingStrategy\n{\n decimal CalculateCost(Order order);\n}\n\n// 2. 具体策略\npublic class CourierShipping : IShippingStrategy\n{\n public decimal CalculateCost(Order order) => order.Weight * 5.0m + 100;\n}\n\npublic class PostShipping : IShippingStrategy\n{\n public decimal CalculateCost(Order order) => order.Weight * 2.0m + 50;\n}\n\npublic class PickupShipping : IShippingStrategy\n{\n public decimal CalculateCost(Order