悠悠楠杉
C设计模式之简单工厂和工厂方法
在C#开发中,设计模式是提升代码质量、增强系统可维护性的关键手段。其中,工厂模式作为创建型设计模式的重要代表,广泛应用于对象创建的场景中。它通过将对象的实例化过程封装起来,降低客户端与具体类之间的耦合度。本文将重点探讨两种常见的工厂模式:简单工厂和工厂方法,并结合C#语言特性进行实现与对比。
先来看简单工厂模式。它并不是GoF(Gang of Four)23种设计模式之一,但由于其结构简单、易于理解,在中小型项目中应用广泛。简单工厂的核心思想是定义一个专门负责创建其他类实例的类,这个类通常是一个静态类或包含静态方法的类。假设我们正在开发一个图形绘制系统,需要支持绘制圆形、矩形等图形。如果在客户端直接使用new Circle()或new Rectangle(),那么一旦新增图形类型,就需要修改多处代码,违反了“开闭原则”。
此时,我们可以引入一个ShapeFactory类:
csharp
public abstract class Shape
{
public abstract void Draw();
}
public class Circle : Shape
{
public override void Draw() => Console.WriteLine("绘制一个圆形");
}
public class Rectangle : Shape
{
public override void Draw() => Console.WriteLine("绘制一个矩形");
}
public static class ShapeFactory
{
public static Shape CreateShape(string shapeType)
{
return shapeType.ToLower() switch
{
"circle" => new Circle(),
"rectangle" => new Rectangle(),
_ => throw new ArgumentException("不支持的图形类型")
};
}
}
客户端调用时只需传入类型字符串:
csharp
var shape = ShapeFactory.CreateShape("circle");
shape.Draw();
这种方式将对象创建逻辑集中管理,避免了散落在各处的new操作。但它的缺点也很明显:每当新增图形类型,就必须修改CreateShape方法,违反了“对修改关闭”的原则。此外,它依赖于条件判断,不利于扩展。
为了解决这个问题,工厂方法模式应运而生。它属于GoF正式设计模式之一,核心在于定义一个用于创建对象的接口,但让子类决定实例化哪一个类。工厂方法把实例化的责任推迟到子类。
我们重构上面的例子,引入抽象工厂接口:
csharp
public abstract class ShapeFactory
{
public abstract Shape CreateShape();
}
public class CircleFactory : ShapeFactory
{
public override Shape CreateShape() => new Circle();
}
public class RectangleFactory : ShapeFactory
{
public override Shape CreateShape() => new Rectangle();
}
此时,客户端不再直接创建具体形状,而是依赖于具体的工厂:
csharp
ShapeFactory factory = new CircleFactory();
Shape shape = factory.CreateShape();
shape.Draw();
这种设计的优势在于,新增图形类型时,只需添加新的形状类和对应的工厂类,无需修改已有代码,完全符合开闭原则。同时,由于每个工厂职责单一,代码更清晰,便于单元测试和维护。
进一步地,我们可以结合依赖注入(DI)容器,将工厂的创建过程也交由框架管理。例如在ASP.NET Core中,可以通过IServiceCollection注册不同工厂,运行时根据配置选择具体实现,从而实现真正的解耦。
总结来说,简单工厂适用于产品种类固定、变化不频繁的场景,适合快速开发;而工厂方法更适合产品族复杂、需要灵活扩展的系统,虽然代码量稍多,但长期维护成本更低。在实际项目中,开发者应根据业务需求权衡选择。掌握这两种模式,不仅能写出更优雅的C#代码,更能培养良好的面向对象设计思维。
