什么时候使用工厂模式❓
当创建逻辑比较复杂,是一个大工程的时候,就可以去考虑使用工厂模式,封装对象的创建过程,将对象的创建和使用分离,比如以下两张情况
类似规则配置解析的例子,代码中存在if-else 分支判断,动态的根据 不同的类型创建不同的对象。针对这种情况,我们就考虑使用工厂模式,将这一大坨if - else 创建对象的代码抽离出来,放到工厂类中
还有一种情况,尽管不需要根据不同的类型创建不同的对象,但是,单个对象本身的创建过程比较复杂,比如 要组合其他的类对象,做各种初始化的操作,在这种情况下,我们也可以考虑使用工厂模式,将对象的创建过程封装到工厂类中。
对于第一种情况,当每个对象的创建逻辑都比较简单的时候,推荐使用简单工厂模式,将对个对象的创建逻辑放到一个工厂类中,当美国个对象的创建逻辑都比较复杂的时候,为了避免设计一个过于庞大的简单工厂类,就推荐使用工厂方法模式,将创建逻辑拆分的更细,美国个对象的创建逻辑独立到各自的工厂类中。同理,对于第二种情况,因为单个对象本身的创建逻辑就比较复杂,所以,建议使用工厂方法模式
除了刚刚提到的几种情况之外,如果创建对象的逻辑并复杂,那我们就直接通过NEW 来创建对象就可以了 ,不需要使用工厂模式!
现在上升一个思维模式来看工厂模式,他的作用无外乎下面几个。这也是判断要不要使用工厂模式的最本质的参考标准。
封装变化:创建逻辑有可能变化,封装成工厂类之后,创建逻辑的变更对到用着更透明。
代码复用:创建代码抽离到独立的工厂类之后可以复用
隔离复杂性:封装复杂的创建逻辑,调用者无需了解如何创建对象。
控制复杂度:将创建代码抽离出来,让原本的函数或者类更加职责单一,代码更简洁。
代码示例
简单工厂
// 示例:图形绘制工具
// 产品接口
public interface IShape
{
void Draw();
}
// 具体产品
public class Circle : IShape
{
public void Draw() => Console.WriteLine("绘制圆形");
}
public class Rectangle : IShape
{
public void Draw() => Console.WriteLine("绘制矩形");
}
// 简单工厂
public class ShapeFactory
{
public IShape CreateShape(string shapeType)
{
switch (shapeType.ToLower())
{
case "circle":
return new Circle();
case "rectangle":
return new Rectangle();
default:
throw new ArgumentException("不支持的图形类型");
}
}
}
// 使用
var factory = new ShapeFactory();
IShape circle = factory.CreateShape("circle");
circle.Draw(); // 输出: 绘制圆形
特点
工厂类集中了所有产品的创建逻辑。
违反 开闭原则(新增产品需修改工厂类代码)。
工厂方法(Factory Method)
// 示例:日志记录器
// 产品接口
public interface ILogger
{
void Log(string message);
}
// 具体产品
public class FileLogger : ILogger
{
public void Log(string message) => Console.WriteLine($"文件日志: {message}");
}
public class DatabaseLogger : ILogger
{
public void Log(string message) => Console.WriteLine($"数据库日志: {message}");
}
// 工厂接口
public interface ILoggerFactory
{
ILogger CreateLogger();
}
// 具体工厂
public class FileLoggerFactory : ILoggerFactory
{
public ILogger CreateLogger() => new FileLogger();
}
public class DatabaseLoggerFactory : ILoggerFactory
{
public ILogger CreateLogger() => new DatabaseLogger();
}
// 使用
ILoggerFactory factory = new FileLoggerFactory();
ILogger logger = factory.CreateLogger();
logger.Log("测试消息"); // 输出: 文件日志: 测试消息
特点
符合 开闭原则(新增产品只需添加新工厂类)。
每个工厂类只负责一种产品,职责单一。
抽象工厂(Abstract Factory)
核心思想:提供一个接口,用于创建 相关或依赖的一组对象(产品族)。
适用场景:需要创建多个关联产品,且产品族可能变化。要创建多个关联产品,且产品族可能变化。
// 产品接口
public interface IButton
{
void Render();
}
public interface ITextBox
{
void Display();
}
// 具体产品 - 浅色主题
public class LightButton : IButton
{
public void Render() => Console.WriteLine("浅色按钮");
}
public class LightTextBox : ITextBox
{
public void Display() => Console.WriteLine("浅色文本框");
}
// 具体产品 - 深色主题
public class DarkButton : IButton
{
public void Render() => Console.WriteLine("深色按钮");
}
public class DarkTextBox : ITextBox
{
public void Display() => Console.WriteLine("深色文本框");
}
// 抽象工厂接口
public interface IThemeFactory
{
IButton CreateButton();
ITextBox CreateTextBox();
}
// 具体工厂 - 浅色主题工厂
public class LightThemeFactory : IThemeFactory
{
public IButton CreateButton() => new LightButton();
public ITextBox CreateTextBox() => new LightTextBox();
}
// 具体工厂 - 深色主题工厂
public class DarkThemeFactory : IThemeFactory
{
public IButton CreateButton() => new DarkButton();
public ITextBox CreateTextBox() => new DarkTextBox();
}
// 使用
IThemeFactory factory = new DarkThemeFactory();
IButton button = factory.CreateButton();
ITextBox textBox = factory.CreateTextBox();
button.Render(); // 输出: 深色按钮
textBox.Display(); // 输出: 深色文本框