【设计模式】-工厂模式
工厂模式是一种创建型设计模式,它提供了一种在不指定具体类的情况下创建对象的方法。工厂模式的核心思想是将对象的创建与使用分离,降低系统的耦合度,使系统更加灵活、可扩展。
工厂模式主要分为三种类型:简单工厂模式、工厂方法模式和抽象工厂模式。下面我将分别介绍这三种工厂模式,并给出相应的Java实例代码。
三种模式介绍
1. 简单工厂模式
简单工厂模式又称为静态工厂方法模式,它由一个工厂类根据传入的参数决定创建哪一种产品类的实例。
Java实例代码:
// 产品接口
public interface Car {
void drive();
}
// 具体产品类1
public class BMW implements Car {
@Override
public void drive() {
System.out.println("Driving BMW");
}
}
// 具体产品类2
public class Benz implements Car {
@Override
public void drive() {
System.out.println("Driving Benz");
}
}
// 工厂类
public class CarFactory {
public static Car createCar(String type) {
if ("BMW".equalsIgnoreCase(type)) {
return new BMW();
} else if ("Benz".equalsIgnoreCase(type)) {
return new Benz();
} else {
throw new IllegalArgumentException("Invalid car type: " + type);
}
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Car bmw = CarFactory.createCar("BMW");
bmw.drive();
Car benz = CarFactory.createCar("Benz");
benz.drive();
}
}
2. 工厂方法模式
工厂方法模式将对象的创建延迟到子类中进行,工厂类不再负责具体产品的创建,而是提供一个创建产品的抽象方法,由子类实现具体的创建逻辑。
Java实例代码:
// 产品接口
public interface Car {
void drive();
}
// 具体产品类1
public class BMW implements Car {
@Override
public void drive() {
System.out.println("Driving BMW");
}
}
// 具体产品类2
public class Benz implements Car {
@Override
public void drive() {
System.out.println("Driving Benz");
}
}
// 工厂接口
public interface CarFactory {
Car createCar();
}
// 具体工厂类1
public class BMWFactory implements CarFactory {
@Override
public Car createCar() {
return new BMW();
}
}
// 具体工厂类2
public class BenzFactory implements CarFactory {
@Override
public Car createCar() {
return new Benz();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
CarFactory bmwFactory = new BMWFactory();
Car bmw = bmwFactory.createCar();
bmw.drive();
CarFactory benzFactory = new BenzFactory();
Car benz = benzFactory.createCar();
benz.drive();
}
}
3. 抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)提供了一种方式来封装一组具有共同主题的单个工厂,而不需要指定它们的具体类。客户端使用抽象工厂来创建一系列的相关或相互依赖的对象,而不需要指定它们具体的类。这样可以将客户端与具体产品的创建分离,使得系统更易于扩展和维护。
下面是一个简单的Java代码实例,展示了抽象工厂模式的应用:
// 抽象产品A
public interface Gui {
void draw();
}
// 具体产品A1
public class WinGui implements Gui {
@Override
public void draw() {
System.out.println("Drawing Windows GUI");
}
}
// 具体产品A2
public class MacGui implements Gui {
@Override
public void draw() {
System.out.println("Drawing MacOS GUI");
}
}
// 抽象产品B
public interface Button {
void click();
}
// 具体产品B1
public class WinButton implements Button {
@Override
public void click() {
System.out.println("Clicking Windows Button");
}
}
// 具体产品B2
public class MacButton implements Button {
@Override
public void click() {
System.out.println("Clicking MacOS Button");
}
}
// 抽象工厂
public interface UiFactory {
Gui createGui();
Button createButton();
}
// 具体工厂1
public class WinUiFactory implements UiFactory {
@Override
public Gui createGui() {
return new WinGui();
}
@Override
public Button createButton() {
return new WinButton();
}
}
// 具体工厂2
public class MacUiFactory implements UiFactory {
@Override
public Gui createGui() {
return new MacGui();
}
@Override
public Button createButton() {
return new MacButton();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
// 使用Windows风格的UI组件
UiFactory winFactory = new WinUiFactory();
Gui winGui = winFactory.createGui();
Button winButton = winFactory.createButton();
winGui.draw();
winButton.click();
// 使用MacOS风格的UI组件
UiFactory macFactory = new MacUiFactory();
Gui macGui = macFactory.createGui();
Button macButton = macFactory.createButton();
macGui.draw();
macButton.click();
}
}
在这个例子中,我们定义了两个抽象产品:Gui
和 Button
,分别代表图形用户界面和按钮。然后,我们为每种操作系统(Windows和MacOS)创建了具体的产品实现。WinGui
和 MacGui
是 Gui
的具体实现,而 WinButton
和 MacButton
是 Button
的具体实现。
我们定义了一个抽象工厂接口 UiFactory
,它包含了创建 Gui
和 Button
的方法。然后,我们为每种操作系统创建了一个具体的工厂实现:WinUiFactory
和 MacUiFactory
。这些工厂负责创建对应操作系统的具体产品实例。
在客户端代码中,我们可以根据需要选择使用哪种风格的UI组件。通过创建不同风格的工厂实例,并调用其创建方法,我们可以得到对应风格的 Gui
和 Button
对象,并调用它们的方法。这样,客户端代码与具体产品的创建逻辑被完全分离,提高了系统的灵活性和可维护性。
对比
是不是还有点晕,好像“工厂方法模式”和“抽象工厂模式”傻傻分不清楚啊。那我们来张表对比一下,就清晰了:
特性/模式 | 简单工厂模式 | 工厂方法模式 | 抽象工厂模式 |
---|---|---|---|
结构 | 一个工厂类负责创建所有产品 | 抽象工厂类定义接口,具体工厂类负责创建对应产品 | 抽象工厂类定义创建产品族的接口,具体工厂类负责创建多个具体产品 |
扩展性 | 不符合“开闭原则”,新增产品需修改工厂类 | 符合“开闭原则”,新增产品只需添加新类和工厂子类 | 新增产品族符合“开闭原则”,单独新增产品不符合 |
使用场景 | 产品种类少且不常变动 | 产品种类多且经常变动 | 需要创建一系列相互关联或依赖的产品 |
责任划分 | 工厂类负责创建所有产品实例 | 具体工厂子类负责创建对应产品实例 | 具体工厂子类负责创建多个相互关联的产品实例 |
客户端与产品创建 | 客户端直接调用工厂类创建产品 | 客户端通过工厂子类接口创建产品 | 客户端通过工厂子类接口创建多个相关产品 |
灵活性 | 较低,工厂类集中了所有产品创建逻辑 | 较高,产品创建逻辑分散在工厂子类中 | 较高,可以灵活创建多个相关产品 |
代码复杂性 | 较低,结构简单 | 中等,需要定义抽象工厂和具体工厂类 | 较高,涉及多个抽象产品类和具体产品类 |
了解下“产品族”是个啥:
在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。这些产品虽然在类型上有所差异,但它们在功能上是相互关联或依赖的。
为了更好地理解这个概念,我们可以以一个实际的例子来说明。假设有一个电器制造工厂,它生产了电视机和电冰箱两种产品。这两种产品分别属于不同的产品等级结构:电视机有其自己的产品等级结构,包括不同品牌、型号的电视机;电冰箱也有其独立的产品等级结构,涵盖了各种类型、规格的电冰箱。然而,在这个例子中,由于它们都是由同一个电器制造工厂生产的,因此电视机和电冰箱构成了一个产品族。
这个产品族中的每个成员(即电视机和电冰箱)都有其特定的功能和用途,但它们都是电器制造工厂的产品,共享了相同的生产标准和质量控制体系。因此,它们在功能上是相互关联或依赖的,构成了一个有机的整体。
抽象工厂模式通过提供一个接口,使得客户端可以创建一系列相关或相互依赖的对象,而无需指定它们具体的类。在上面的例子中,客户端可以通过调用电器制造工厂的接口,一次性地获取到电视机和电冰箱这两种产品,而无需关心它们具体的实现细节。
这下是不是就清晰了。OVER。