0Pricing
Java Academy · 课时

工厂方法模式

在基类中定义工厂方法,并让子类决定要创建哪种产品

工厂方法模式 是 CoddyKit 上的免费 Java Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

工厂方法的意图

工厂方法定义了用于创建对象的接口,但将决定实例化哪个类的责任交给子类。它将创建逻辑与客户端代码解耦。

没有工厂方法时的问题

没有工厂时,客户端代码中会充斥着 new ConcreteClass() 调用。添加新变体意味着必须修改每个调用位置——这违反了开闭原则。

// Client knows too much:
Shape shape;
if (type.equals("circle")) shape = new Circle(r);
else if (type.equals("rect")) shape = new Rectangle(w, h);
// Every new shape requires editing this code.

创建者抽象类

请定义一个抽象创建者类,并在其中声明 createProduct() 工厂方法。子类重写该方法,以返回特定的产品类型。

public abstract class Dialog {
    public void render() {
        Button btn = createButton(); // factory method
        btn.onClick();
    }
    protected abstract Button createButton();
}

具体创建者

每个子类都重写工厂方法,以返回适当的产品,同时无需修改基类中的外围算法。

public class WindowsDialog extends Dialog {
    @Override
    protected Button createButton() { return new WindowsButton(); }
}
public class WebDialog extends Dialog {
    @Override
    protected Button createButton() { return new HtmlButton(); }
}

产品接口

所有具体产品都实现同一个公共接口,这样创建者就能以通用方式使用它们。

public interface Button {
    void onClick();
    void render();
}
public class WindowsButton implements Button {
    public void onClick() { System.out.println("Windows click"); }
    public void render() { System.out.println("Render Windows button"); }
}

静态工厂方法与工厂方法模式

静态工厂方法(例如 LocalDate.of())是一种命名约定,而不是 GoF 模式。GoF 模式使用继承;静态工厂则在单个类上使用静态方法。

// Static factory (NOT the GoF pattern)
LocalDate d = LocalDate.of(2024, 6, 15);
// GoF Factory Method uses a class hierarchy

参数化工厂方法

向工厂方法传入参数,即可在多个产品之间进行选择,而无需为每种产品都创建一个子类。

public class ShapeFactory {
    public static Shape create(String type, double... dims) {
        return switch (type) {
            case "circle"    -> new Circle(dims[0]);
            case "rectangle" -> new Rectangle(dims[0], dims[1]);
            default -> throw new IllegalArgumentException("Unknown: " + type);
        };
    }
}

使用泛型的工厂方法

使用泛型可以让工厂方法具备类型安全,并能在不同的产品族之间复用。

public abstract class Repository<T, ID> {
    public abstract T findById(ID id);
    protected abstract T createEmpty(); // factory method
}

使用 Map 注册工厂

基于注册表的工厂会将类型字符串映射到 Supplier lambda,从而避免使用 if-else 链,并使注册过程具有动态性。

Map<String, Supplier<Notification>> registry = new HashMap<>();
registry.put("email", EmailNotification::new);
registry.put("sms",   SmsNotification::new);
Notification n = registry.getOrDefault(type, DefaultNotification::new).get();

工厂方法与抽象工厂

工厂方法通过继承创建一种产品类型。抽象工厂通过组合创建一组相关产品。当只有一种产品会发生变化时,请使用工厂方法;当整套产品需要一起变化时,请使用抽象工厂。

现实示例:Logger 工厂

SLF4J 的 LoggerFactory.getLogger(Class) 是一个静态工厂,它会返回正确的日志记录器实现(Logback、Log4j 或 JUL),而调用方无需知道具体是哪一种实现。

Logger log = LoggerFactory.getLogger(MyService.class);
log.info("Service started");

快速检查

工厂方法模式的关键特征是什么?

回顾

工厂方法将实例化决策放入可重写的子类方法中,从而把对象创建与客户端解耦。当一个类无法预先确定需要创建哪些对象时,请使用它。

常见问题解答

「工厂方法模式」课时是免费的吗?

是的 — 「工厂方法模式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「工厂方法模式」这节课中我会学到什么?

在基类中定义工厂方法,并让子类决定要创建哪种产品 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「工厂方法模式」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Singleton:线程安全的实现
  2. 工厂方法模式
  3. 面向产品族的抽象工厂
  4. 使用流式 API 的建造者模式
← 返回 Java Academy