Menu
CoddyTech

工厂模式

本课属于 Coddy C# 学习旅程的“面向对象编程”单元。第 53 课,共 70 课。

工厂模式是一种创建型模式,它将对象的创建交给单独的方法或类。你不必在代码中直接使用 new,而是让工厂为你创建对象。这样可以集中管理创建逻辑,让代码更灵活。

设想这样一种情况:你需要创建不同类型的文档。如果没有工厂,你的代码就会与特定的类紧密耦合:

// 不使用工厂模式:创建逻辑分散在各处
IDocument doc;
if (type == "pdf")
    doc = new PdfDocument();
else if (type == "word")
    doc = new WordDocument();

工厂将这项决策封装在一个地方:

public interface IDocument
{
    void Open();
}
public class PdfDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening PDF");
}
public class WordDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening Word");
}
public class DocumentFactory
{
    public IDocument Create(string type)
    {
        switch (type)
        {
            case "pdf":
                return new PdfDocument();
            case "word":
                return new WordDocument();
            default:
                throw new ArgumentException("Unknown type");
        }
    }
}

现在,客户端代码只需请求所需内容,无需了解具体的类:

var factory = new DocumentFactory();
IDocument doc = factory.Create("pdf");
doc.Open();  // 打开 PDF

当你之后需要添加新类型时,工厂模式就能发挥优势。添加 SpreadsheetDocument 只需要修改工厂,而不必在创建文档的所有地方都进行修改。这种分离让你的代码库更易于维护和测试。

challenge icon

挑战

简单

我们来使用工厂模式构建一个通知系统。你不必在代码中到处直接创建不同类型的通知,而是可以将创建逻辑集中在一个工厂类中,由它根据简单的字符串标识符决定要创建哪种通知。

你会将代码分成三个文件:

  • Notification.cs:在 Notifications 命名空间中定义 INotification 接口,其中包含一个返回字符串的 Send(string message) 方法。然后创建三个实现此接口的类:
    • EmailNotification:返回 "Email: {message}"
    • SmsNotification:返回 "SMS: {message}"
    • PushNotification:返回 "Push: {message}"
  • NotificationFactory.cs:在同一命名空间中创建 NotificationFactory 类,并添加 Create(string type) 方法,根据类型字符串返回相应的 INotification:
    • "email" 返回一个 EmailNotification
    • "sms" 返回一个 SmsNotification
    • "push" 返回一个 PushNotification
    对于任何无法识别的类型,默认返回一个 EmailNotification。
  • Program.cs:创建一个工厂实例,并使用它根据输入创建通知,从而将所有部分组合起来。由工厂负责决定要实例化哪个具体类。

你会收到两个输入:

  • 通知类型(例如,sms)
  • 要发送的消息(例如,Your order has shipped)

使用工厂创建相应的通知类型,然后调用它的 Send 方法传入消息,并打印结果。

例如,如果输入是 push 和 Meeting in 5 minutes,输出应为:

Push: Meeting in 5 minutes

注意,主代码中不会使用 new EmailNotification() 或类似写法,而是直接向工厂请求所需的通知。如果之后添加 SlackNotification,你只需更新工厂,而不必修改每个创建通知的地方!

亲手试试

using System;
using Notifications;

class Program
{
    public static void Main(string[] args)
    {
        // 读取输入
        string type = Console.ReadLine();
        string message = Console.ReadLine();

        // TODO:创建一个 NotificationFactory 实例

        // TODO:使用工厂创建对应的通知

        // TODO:调用 Send 方法并打印结果
    }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C# 在线编译器