在软件开发中,对象的创建是不可避免的。然而,当系统中存在多个对象需要创建时,直接在代码中使用 new 关键字可能会导致代码的可维护性和可扩展性变差。工厂模式(Factory Pattern)正是为了解决这一问题而诞生的。它是一种创建型设计模式,通过封装对象的创建逻辑,让客户端代码无需直接调用构造函数,从而实现更灵活、更高效的对象创建。
一、工厂模式是什么?
工厂模式的核心思想是**“封装对象的创建逻辑”**。它通过一个工厂类来负责创建对象,而不是让客户端直接调用构造函数。这样做的好处是,当对象的创建逻辑发生变化时,我们只需要修改工厂类,而无需修改客户端代码。
工厂模式有三种常见的形式:简单工厂模式、工厂方法模式和抽象工厂模式。它们的复杂度和适用场景各有不同。下面我们逐一介绍这三种模式。
二、简单工厂模式
简单工厂模式是最基础的工厂模式。它通过一个工厂类来创建对象,但这个工厂类通常会包含所有对象的创建逻辑。
(一)简单工厂模式的实现
假设我们有一个 Shape 接口,以及多个实现类(如 Circle、Square、Rectangle 等)。我们希望客户端代码能够通过一个工厂类来创建这些对象,而不是直接调用构造函数。
// Shape 接口
public interface Shape {
void draw();
}
// Circle 类
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
// Square 类
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
// Rectangle 类
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
// 简单工厂类
public class ShapeFactory {
public Shape getShape(String shapeType) {
if (shapeType == null) {
return null;
}
if (shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
} else if (shapeType.equalsIgnoreCase("SQUARE")) {
return new Square();
} else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
return new Rectangle();
}
return null;
}
}
(二)简单工厂模式的优点
- 封装创建逻辑:客户端代码无需直接调用构造函数,而是通过工厂类来创建对象。
- 易于扩展:如果需要添加新的对象类型,只需在工厂类中添加新的分支逻辑即可。
(三)简单工厂模式的缺点
- 违反开闭原则:当需要添加新的对象类型时,必须修改工厂类的代码,这违反了开闭原则(对扩展开放,对修改封闭)。
- 工厂类职责过重:工厂类包含了所有对象的创建逻辑,随着对象类型的增加,工厂类会变得越来越庞大。
三、工厂方法模式
工厂方法模式是对简单工厂模式的改进。它通过引入一个工厂接口,让每个具体的工厂类负责创建具体的对象。这样可以更好地遵循开闭原则。
(一)工厂方法模式的实现
我们仍然使用 Shape 接口和对应的实现类,但这次我们引入一个工厂接口和多个具体的工厂类。
// Shape 接口
public interface Shape {
void draw();
}
// Circle 类
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
// Square 类
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
// Rectangle 类
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
// 工厂接口
public interface ShapeFactory {
Shape getShape();
}
// CircleFactory 类
public class CircleFactory implements ShapeFactory {
@Override
public Shape getShape() {
return new Circle();
}
}
// SquareFactory 类
public class SquareFactory implements ShapeFactory {
@Override
public Shape getShape() {
return new Square();
}
}
// RectangleFactory 类
public class RectangleFactory implements ShapeFactory {
@Override
public Shape getShape() {
return new Rectangle();
}
}
(二)工厂方法模式的优点
- 遵循开闭原则:当需要添加新的对象类型时,只需添加新的工厂类,而无需修改现有的工厂类。
- 职责清晰:每个工厂类只负责创建一种对象,职责单一。
(三)工厂方法模式的缺点
- 代码量增加:需要为每种对象类型定义一个工厂类,代码量可能会增加。
- 灵活性受限:客户端需要知道具体的工厂类,这在某些场景下可能会限制灵活性。
四、抽象工厂模式
抽象工厂模式是工厂模式的高级形式。它通过一个工厂接口定义一组相关对象的创建方法,而具体的工厂类则负责实现这些方法。抽象工厂模式适用于对象类型较多且存在关联关系的场景。
(一)抽象工厂模式的实现
假设我们不仅有 Shape 接口,还有 Color 接口,以及对应的实现类。我们希望客户端可以通过一个工厂类来创建一组相关的对象。
// Shape 接口
public interface Shape {
void draw();
}
// Circle 类
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
// Square 类
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
// Color 接口
public interface Color {
void fill();
}
// Red 类
public class Red implements Color {
@Override
public void fill() {
System.out.println("Inside Red::fill() method.");
}
}
// Green 类
public class Green implements Color {
@Override
public void fill() {
System.out.println("Inside Green::fill() method.");
}
}
// 抽象工厂接口
public interface AbstractFactory {
Color getColor(String color);
Shape getShape(String shape);
}
// ShapeFactory 类
public class ShapeFactory implements AbstractFactory {
@Override
public Color getColor(String color) {
return null;
}
@Override
public Shape getShape(String shapeType) {
if (shapeType == null) {
return null;
}
if (shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
} else if (shapeType.equalsIgnoreCase("SQUARE")) {
return new Square();
}
return null;
}
}
// ColorFactory 类
public class ColorFactory implements AbstractFactory {
@Override
public Color getColor(String colorType) {
if (colorType == null) {
return null;
}
if (colorType.equalsIgnoreCase("RED")) {
return new Red();
} else if (colorType.equalsIgnoreCase("GREEN")) {
return new Green();
}
return null;
}
@Override
public Shape getShape(String shape) {
return null;
}
}
// 工厂生成器
public class FactoryProducer {
public static AbstractFactory getFactory(String choice) {
if (choice.equalsIgnoreCase("SHAPE")) {
return new ShapeFactory();
} else if (choice.equalsIgnoreCase("COLOR")) {
return new ColorFactory();
}
return null;
}
}
(二)抽象工厂模式的优点
- 高内聚性:每个工厂类只负责创建一组相关的对象,职责清晰。
- 易于扩展:当需要添加新的对象类型时,只需添加新的工厂类即可。
- 解耦客户端与具体实现:客户端通过抽象工厂接口与具体实现解耦,灵活性更高。
(三)抽象工厂模式的缺点
- 代码复杂度增加:需要定义多个接口和类,代码复杂度较高。
- 灵活性受限:如果对象之间的关系发生变化,可能需要修改工厂接口。
五、工厂模式的应用场景
工厂模式在实际开发中非常常见,以下是一些典型的应用场景:
- 创建对象时需要大量重复代码:通过工厂模式可以封装创建逻辑,减少重复代码。
- 对象的创建依赖于外部配置:通过工厂模式可以根据配置动态创建对象。
- 对象类型较多且存在关联关系:抽象工厂模式适用于这种场景,可以灵活创建一组相关对象。
六、总结
工厂模式是一种非常实用的创建型设计模式,通过封装对象的创建逻辑,让客户端代码更加简洁、灵活。简单工厂模式适合简单的场景,工厂方法模式适合对象类型较多的场景,而抽象工厂模式则适合对象类型较多且存在关联关系的场景。
在实际开发中,选择合适的工厂模式需要根据具体需求权衡。无论你选择哪种工厂模式,它都能帮助你更好地管理对象的创建逻辑,提升代码的可维护性和可扩展性。
希望这篇文章能帮助你更好地理解工厂模式。如果你对工厂模式还有疑问,欢迎在评论区留言,我们一起探讨!
在接下来的推文中,我们将继续探索其他设计模式,帮助你更好地理解和应用它们。让我们一起在设计模式的海洋中继续探索!


3127

被折叠的 条评论
为什么被折叠?



