设计模式-工厂模式

工厂模式的介绍

什么是工厂模式?

工厂模式是一种创建型设计模式,它提供了一个创建对象的接口,让子类决定实例化哪一个类。工厂模式分为两种主要类型:工厂方法模式(Factory Method)和抽象工厂模式(Abstract Factory)。它们都旨在隐藏对象的创建逻辑,减少客户端代码与具体类的耦合。

工厂方法模式的详细说明

工厂方法模式通过继承让子类决定实例化哪个类,适合当一个类无法预先知道它需要创建的对象类型时,因为对象类型在运行时确定。例如,在创建不同类型的计算机(如PC和服务器)时,可以使用工厂方法模式。

以下是一个Java示例,展示如何创建PC和服务器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public abstract class Computer {
public abstract String getRAM();
public abstract String getHDD();
public abstract String getCPU();
@Override
public String toString() {
return "RAM= " + this.getRAM() + ", HDD=" + this.getHDD() + ", CPU=" + this.getCPU();
}
}

public class PC extends Computer {
private String ram;
private String hdd;
private String cpu;
public PC(String ram, String hdd, String cpu){
this.ram=ram;
this.hdd=hdd;
this.cpu=cpu;
}
@Override
public String getRAM() { return this.ram; }
@Override
public String getHDD() { return this.hdd; }
@Override
public String getCPU() { return this.cpu; }
}

public class Server extends Computer {
private String ram;
private String hdd;
private String cpu;
public Server(String ram, String hdd, String cpu){
this.ram=ram;
this.hdd=hdd;
this.cpu=cpu;
}
@Override
public String getRAM() { return this.ram; }
@Override
public String getHDD() { return this.hdd; }
@Override
public String getCPU() { return this.cpu; }
}

public class ComputerFactory {
public static Computer getComputer(String type, String ram, String hdd, String cpu){
if("PC".equalsIgnoreCase(type)) return new PC(ram, hdd, cpu);
else if("Server".equalsIgnoreCase(type)) return new Server(ram, hdd, cpu);
return null;
}
}

public class TestFactory {
public static void main(String[] args) {
Computer pc = ComputerFactory.getComputer("pc","2 GB","500 GB","2.4 GHz");
Computer server = ComputerFactory.getComputer("server","16 GB","1 TB","2.9 GHz");
System.out.println("Factory PC Config::"+pc);
System.out.println("Factory Server Config::"+server);
}
}

输出结果:

1
2
Factory PC Config::RAM= 2 GB, HDD=500 GB, CPU=2.4 GHz
Factory Server Config::RAM= 16 GB, HDD=1 TB, CPU=2.9 GHz

抽象工厂模式的详细说明

抽象工厂模式通过组合创建相关或依赖对象的家族,而不需要指定它们的具体类。它适合需要创建一系列相关对象的情况,例如为不同公司创建不同类型的车辆。

以下是一个Java示例,展示如何为FutureVehicle和NextGen公司创建摩托车和电动车:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public interface MotorVehicle {
void build();
}

public interface ElectricVehicle {
void build();
}

public class FutureVehicleMotorcycle implements MotorVehicle {
@Override
public void build() {
System.out.println("Building FutureVehicleMotorcycle");
}
}

public class FutureVehicleElectricCar implements ElectricVehicle {
@Override
public void build() {
System.out.println("Building FutureVehicleElectricCar");
}
}

public class NextGenMotorcycle implements MotorVehicle {
@Override
public void build() {
System.out.println("Building NextGenMotorcycle");
}
}

public class NextGenElectricCar implements ElectricVehicle {
@Override
public void build() {
System.out.println("Building NextGenElectricCar");
}
}

public abstract class Corporation {
public abstract MotorVehicle createMotorVehicle();
public abstract ElectricVehicle createElectricVehicle();
}

public class FutureVehicleCorporation extends Corporation {
@Override
public MotorVehicle createMotorVehicle() {
return new FutureVehicleMotorcycle();
}
@Override
public ElectricVehicle createElectricVehicle() {
return new FutureVehicleElectricCar();
}
}

public class NextGenCorporation extends Corporation {
@Override
public MotorVehicle createMotorVehicle() {
return new NextGenMotorcycle();
}
@Override
public ElectricVehicle createElectricVehicle() {
return new NextGenElectricCar();
}
}

public class Client {
public static void main(String[] args) {
Corporation futureCorp = new FutureVehicleCorporation();
MotorVehicle futureMotorcycle = futureCorp.createMotorVehicle();
ElectricVehicle futureElectricCar = futureCorp.createElectricVehicle();
futureMotorcycle.build();
futureElectricCar.build();

Corporation nextGenCorp = new NextGenCorporation();
MotorVehicle nextGenMotorcycle = nextGenCorp.createMotorVehicle();
ElectricVehicle nextGenElectricCar = nextGenCorp.createElectricVehicle();
nextGenMotorcycle.build();
nextGenElectricCar.build();
}
}

输出结果:

1
2
3
4
Building FutureVehicleMotorcycle
Building FutureVehicleElectricCar
Building NextGenMotorcycle
Building NextGenElectricCar

工厂方法模式与抽象工厂模式的比较

特性工厂方法模式抽象工厂模式
实现方式使用继承,让子类决定实例化哪个类使用组合,委托给另一个对象
创建对象创建单一类型的对象创建相关对象的家族
复杂性简单,直接更复杂,提供更多灵活性
适用场景动态创建单一类型对象创建一系列相关对象,系统独立于产品创建

工厂模式的优点与应用场景

优点

  • 封装:隐藏创建逻辑,客户端代码无需关心具体实现。
  • 松耦合:减少类之间的依赖,提高代码可维护性。
  • 可扩展性:易于添加新类型,无需修改现有代码。
  • 单一职责原则:每个类有单一职责,符合设计原则。

应用场景

  • 工厂方法模式:当类无法预先知道需要创建的对象类型,例如根据用户输入创建不同产品。
  • 抽象工厂模式:当系统需要独立于其产品的创建、组合和表示,例如跨平台GUI元素的生产。

详细报告

引言

设计模式是软件开发中的关键概念,特别是在Java编程中,它们为常见问题提供了经过验证的解决方案。本报告旨在为初学者提供全面的指导,涵盖工厂模式的定义、重要性、分类以及具体示例,尤其聚焦于工厂方法模式和抽象工厂模式。基于2025年3月的最新资源,确保信息的时效性和准确性。

设计模式的定义与背景

设计模式是针对软件设计中反复出现问题的通用解决方案。它们不是直接可用的代码,而是指导如何解决问题的模板。根据 GeeksforGeeks 的定义,设计模式在Java中涉及对象和类的结构化方法,旨在解决特定上下文下的反复出现的设计问题。这些模式代表了最佳实践,能够增强代码的灵活性、可重用性和可维护性。

研究表明,设计模式最初由“四人帮”(Gang of Four)在1994年提出,包括23种模式,分为三大类:创建型、结构型和行为型。这些模式并非一成不变,可以根据具体情况进行调整,提供灵活的解决方案。

工厂模式的重要性

工厂模式在软件开发中具有多方面的好处:

  • 重用成功的设计:避免重复发明轮子,利用已有的最佳实践。例如,工厂方法模式确保动态创建对象,适用于根据输入选择子类。
  • 提高代码可读性和可维护性:标准化的模式使代码更易于理解和修改,方便团队协作。根据 Refactoring Guru 的观点,这对于大型项目尤为重要。
  • 促进开发人员之间的沟通:使用共同的语言和模式,团队成员更容易交流设计理念,减少误解。
  • 减少解决常见问题的耗时:工厂模式提供了现成的解决方案,节省了时间和精力,尤其在面对复杂系统时。

然而,需注意设计模式的潜在争议。一些开发者认为,过早使用设计模式可能增加不必要的复杂性,导致代码难以维护。证据显示,在小型项目中,简单解决方案可能更合适,而设计模式更适合需要扩展的大型系统。

工厂模式的分类

根据 Refactoring GuruBaeldung 的分类,工厂模式包括两种主要类型:工厂方法模式和抽象工厂模式,具体如下:

模式名称描述
工厂方法模式定义一个创建对象的接口,让子类决定实例化哪一个类,适合动态创建单一类型对象。
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要指定它们的具体类,适合创建一系列相关对象。

以下是每个模式的详细说明:

工厂方法模式

工厂方法模式通过继承让子类决定实例化哪个类,适合当一个类无法预先知道它需要创建的对象类型时。根据 DigitalOcean 的示例,我们可以创建不同类型的计算机:

  • 结构

    • 产品:声明工厂方法创建的对象的接口。
    • 具体产品:实现产品接口。
    • 创建者:声明工厂方法,返回产品类型的对象。
    • 具体创建者:覆盖工厂方法,返回具体产品的实例。
  • Java示例
    假设我们需要创建PC和服务器,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    public abstract class Computer {
    public abstract String getRAM();
    public abstract String getHDD();
    public abstract String getCPU();
    @Override
    public String toString() {
    return "RAM= " + this.getRAM() + ", HDD=" + this.getHDD() + ", CPU=" + this.getCPU();
    }
    }

    public class PC extends Computer {
    private String ram;
    private String hdd;
    private String cpu;
    public PC(String ram, String hdd, String cpu){
    this.ram=ram;
    this.hdd=hdd;
    this.cpu=cpu;
    }
    @Override
    public String getRAM() { return this.ram; }
    @Override
    public String getHDD() { return this.hdd; }
    @Override
    public String getCPU() { return this.cpu; }
    }

    public class Server extends Computer {
    private String ram;
    private String hdd;
    private String cpu;
    public Server(String ram, String hdd, String cpu){
    this.ram=ram;
    this.hdd=hdd;
    this.cpu=cpu;
    }
    @Override
    public String getRAM() { return this.ram; }
    @Override
    public String getHDD() { return this.hdd; }
    @Override
    public String getCPU() { return this.cpu; }
    }

    public class ComputerFactory {
    public static Computer getComputer(String type, String ram, String hdd, String cpu){
    if("PC".equalsIgnoreCase(type)) return new PC(ram, hdd, cpu);
    else if("Server".equalsIgnoreCase(type)) return new Server(ram, hdd, cpu);
    return null;
    }
    }

    public class TestFactory {
    public static void main(String[] args) {
    Computer pc = ComputerFactory.getComputer("pc","2 GB","500 GB","2.4 GHz");
    Computer server = ComputerFactory.getComputer("server","16 GB","1 TB","2.9 GHz");
    System.out.println("Factory PC Config::"+pc);
    System.out.println("Factory Server Config::"+server);
    }
    }

    输出:

    1
    2
    Factory PC Config::RAM= 2 GB, HDD=500 GB, CPU=2.4 GHz
    Factory Server Config::RAM= 16 GB, HDD=1 TB, CPU=2.9 GHz
  • 优点

    • 封装创建逻辑,客户端代码无需关心具体实现。
    • 减少类之间的依赖,提高代码可维护性。
    • 易于扩展,添加新类型无需修改现有代码。
  • 应用场景

    • 当类无法预先知道需要创建的对象类型,例如根据用户输入创建不同产品。
抽象工厂模式

抽象工厂模式通过组合创建相关或依赖对象的家族,而不需要指定它们的具体类。它适合需要创建一系列相关对象的情况。根据 Baeldung 的示例,我们可以为不同公司创建车辆:

  • 结构

    • 抽象工厂:声明创建抽象产品的操作接口。
    • 具体工厂:实现创建具体产品的操作。
    • 抽象产品:声明产品类型的接口。
    • 具体产品:实现抽象产品接口。
    • 客户端:通过抽象接口使用工厂和产品。
  • Java示例
    假设我们为FutureVehicle和NextGen公司创建摩托车和电动车,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    public interface MotorVehicle {
    void build();
    }

    public interface ElectricVehicle {
    void build();
    }

    public class FutureVehicleMotorcycle implements MotorVehicle {
    @Override
    public void build() {
    System.out.println("Building FutureVehicleMotorcycle");
    }
    }

    public class FutureVehicleElectricCar implements ElectricVehicle {
    @Override
    public void build() {
    System.out.println("Building FutureVehicleElectricCar");
    }
    }

    public class NextGenMotorcycle implements MotorVehicle {
    @Override
    public void build() {
    System.out.println("Building NextGenMotorcycle");
    }
    }

    public class NextGenElectricCar implements ElectricVehicle {
    @Override
    public void build() {
    System.out.println("Building NextGenElectricCar");
    }
    }

    public abstract class Corporation {
    public abstract MotorVehicle createMotorVehicle();
    public abstract ElectricVehicle createElectricVehicle();
    }

    public class FutureVehicleCorporation extends Corporation {
    @Override
    public MotorVehicle createMotorVehicle() {
    return new FutureVehicleMotorcycle();
    }
    @Override
    public ElectricVehicle createElectricVehicle() {
    return new FutureVehicleElectricCar();
    }
    }

    public class NextGenCorporation extends Corporation {
    @Override
    public MotorVehicle createMotorVehicle() {
    return new NextGenMotorcycle();
    }
    @Override
    public ElectricVehicle createElectricVehicle() {
    return new NextGenElectricCar();
    }
    }

    public class Client {
    public static void main(String[] args) {
    Corporation futureCorp = new FutureVehicleCorporation();
    MotorVehicle futureMotorcycle = futureCorp.createMotorVehicle();
    ElectricVehicle futureElectricCar = futureCorp.createElectricVehicle();
    futureMotorcycle.build();
    futureElectricCar.build();

    Corporation nextGenCorp = new NextGenCorporation();
    MotorVehicle nextGenMotorcycle = nextGenCorp.createMotorVehicle();
    ElectricVehicle nextGenElectricCar = nextGenCorp.createElectricVehicle();
    nextGenMotorcycle.build();
    nextGenElectricCar.build();
    }
    }

    输出:

    1
    2
    3
    4
    Building FutureVehicleMotorcycle
    Building FutureVehicleElectricCar
    Building NextGenMotorcycle
    Building NextGenElectricCar
  • 优点

    • 中央化产品创建,减少客户端代码的复杂性。
    • 提供更多灵活性,适合创建相关对象的家族。
  • 应用场景

    • 当系统需要独立于其产品的创建、组合和表示,例如跨平台GUI元素的生产。

工厂方法模式与抽象工厂模式的比较

根据 Baeldung 的分析,两种模式有以下区别:

特性工厂方法模式抽象工厂模式
实现方式使用继承,让子类决定实例化哪个类使用组合,委托给另一个对象
创建对象创建单一类型的对象创建相关对象的家族
复杂性简单,直接更复杂,提供更多灵活性
适用场景动态创建单一类型对象创建一系列相关对象,系统独立于产品创建

进一步学习的资源

为了深入学习工厂模式,推荐以下资源:

结论

工厂模式是提高代码质量和可维护性的强大工具。通过理解和应用工厂方法模式和抽象工厂模式,开发人员可以编写更高效、更具扩展性的软件系统。建议根据项目需求选择合适的设计模式,避免过早优化,同时关注团队沟通和代码可读性。