工厂模式
工厂模式是一种创建型设计模式,它提供了一种创建对象的方式。在工厂模式中,我们使用工厂类来创建对象,而不是直接在代码中使用new关键字来实例化对象。将对象的创建过程封装在一个工厂类中,客户端只需要通过工厂类来获取所需的对象,而无需关心对象的具体创建过程。
工厂模式主要包括三种形式:简单工厂模式、工厂方法模式和抽象工厂模式。
- 简单工厂模式:简单工厂模式是最基本的工厂模式,它通过一个工厂类来创建对象,客户端只需要传入一个参数,工厂类根据参数来决定创建哪种类型的对象。
- 工厂方法模式:工厂方法模式定义一个用于创建对象的接口,让子类来实现具体的对象创建逻辑。每个具体的产品都有对应的工厂类,客户端通过调用工厂方法来获取所需的对象。
- 抽象工厂模式:抽象工厂模式提供一个接口,用于创建一系列相关或依赖对象的家族,而不需要指定具体的类。抽象工厂模式通常包括一个抽象工厂类和多个具体工厂类,每个具体工厂类负责创建一组相关的对象。
工厂模式可以帮助我们实现对象的解耦和灵活性,提高代码的可维护性和可扩展性。在实际项目中,我们可以根据具体需求选择合适的工厂模式来优化代码结构。
适用场景
工厂模式适用于以下场景:
- 当一个类不知道它必须创建的对象的类时,可以使用工厂模式来创建对象,让子类来决定具体实例化哪个类。
- 当一个类希望由它的子类来指定创建对象时,可以使用工厂模式。子类可以提供创建对象的具体实现,从而实现定制化的对象创建。
- 当一个类将创建对象的职责委托给多个帮助子类中的一个,并希望将哪个帮助子类是代理者的信息对类隐藏时,可以使用工厂模式。
- 当一个类希望由子类来指定创建对象时,可以使用工厂模式。这样可以避免在父类中创建对象,从而降低耦合度。
工厂模式的优缺点
优点:
- 封装了对象的创建过程:工厂模式将对象的创建过程封装在工厂类中,客户端只需要关注使用工厂方法获取对象,无需关心对象的具体创建过程,降低了客户端与具体产品类之间的耦合度。
- 提高代码的灵活性:工厂模式可以根据实际需求动态创建对象,使得代码更加灵活,易于扩展和维护。
- 符合开闭原则:工厂模式符合开闭原则,当需要新增产品类时,只需要添加对应的工厂类和产品类,而无需修改已有的代码。
- 降低了代码重复:工厂模式可以避免在多个地方重复创建相同对象的代码,提高了代码的复用性。
- 提高了系统的可测试性:工厂模式使得对象的创建和使用分离,方便进行单元测试和模块化测试。
缺点:
- 增加了类的数量:工厂模式引入了额外的工厂类,可能会增加系统中类的数量,使得代码结构变得复杂。
- 增加了系统的抽象性和理解难度:工厂模式通过抽象工厂、具体工厂、抽象产品、具体产品等多个类之间的关系来实现对象的创建,可能会增加系统的抽象性和理解难度。
- 不易于单独测试产品类:由于产品类的创建由工厂类负责,产品类的创建和使用紧密耦合,不易于单独对产品类进行测试。
简单工厂模式的实现
下面以一个简单的示例来演示如何使用工厂模式实现对象的创建:
假设我们有一个形状接口 Shape,以及两个具体的形状类 Circle 和 Rectangle。我们希望通过一个 ShapeFactory 工厂类来创建具体的形状对象。
首先定义形状接口 Shape:
// Shape 接口
public interface Shape {
void draw();
}
然后定义具体的形状类 Circle 和 Rectangle:
// Circle 类
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
// Rectangle 类
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
接下来定义 ShapeFactory 工厂类,根据客户端的需求来创建具体的形状对象:
// ShapeFactory 工厂类
public class ShapeFactory {
public Shape createShape(String shapeType) {
if (shapeType.equalsIgnoreCase("circle")) {
return new Circle();
} else if (shapeType.equalsIgnoreCase("rectangle")) {
return new Rectangle();
} else {
return null;
}
}
}
最后,客户端代码可以通过 ShapeFactory 来创建具体的形状对象:
public class Client {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
Shape circle = shapeFactory.createShape("circle");
circle.draw();
Shape rectangle = shapeFactory.createShape("rectangle");
rectangle.draw();
}
}
在上面的示例中,通过 ShapeFactory 工厂类来创建具体的形状对象,客户端只需要调用工厂类的方法,无需关心具体的对象创建过程。这样可以实现对象的创建和使用的解耦,提高了代码的灵活性和可维护性。
工厂方法模式的实现
下面以一个简单的示例来演示如何使用工厂方法模式实现对象的创建:
假设我们有一个形状接口 Shape,以及两个具体的形状类 Circle 和 Rectangle。我们希望通过两个具体的工厂类 CircleFactory 和 RectangleFactory 来分别创建 Circle 和 Rectangle 对象。
首先定义形状接口 Shape:
// Shape 接口
public interface Shape {
void draw();
}
然后定义具体的形状类 Circle 和 Rectangle:
// Circle 类
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
// Rectangle 类
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
接下来定义具体的工厂类 CircleFactory 和 RectangleFactory,分别用于创建 Circle 和 Rectangle 对象:
// CircleFactory 工厂类
public class CircleFactory {
public Shape createShape() {
return new Circle();
}
}
// RectangleFactory 工厂类
public class RectangleFactory {
public Shape createShape() {
return new Rectangle();
}
}
最后,客户端代码可以通过具体的工厂类来创建具体的形状对象:
public class Client {
public static void main(String[] args) {
CircleFactory circleFactory = new CircleFactory();
Shape circle = circleFactory.createShape();
circle.draw();
RectangleFactory rectangleFactory = new RectangleFactory();
Shape rectangle = rectangleFactory.createShape();
rectangle.draw();
}
}
在上面的示例中,通过具体的工厂类 CircleFactory 和 RectangleFactory 来创建具体的形状对象,客户端可以根据需要选择不同的工厂类来创建不同的对象。这样可以实现对象的创建和使用的解耦,提高了代码的灵活性和可维护性。
抽象工厂模式的实现
抽象工厂模式是工厂方法模式的升级版,它提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。下面以一个简单的示例来演示如何使用抽象工厂模式:
假设我们有两个产品家族:形状(Shape)和颜色(Color),每个家族有多个具体的产品。我们希望通过一个抽象工厂来创建形状和颜色对象。
首先定义形状接口 Shape 和颜色接口 Color:
// Shape 接口
public interface Shape {
void draw();
}
// Color 接口
public interface Color {
void fill();
}
然后定义具体的形状类 Circle 和 Rectangle,以及具体的颜色类 Red 和 Blue:
// Circle 类
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
// Rectangle 类
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
// Red 类
public class Red implements Color {
@Override
public void fill() {
System.out.println("Filling with red color");
}
}
// Blue 类
public class Blue implements Color {
@Override
public void fill() {
System.out.println("Filling with blue color");
}
}
接下来定义抽象工厂接口 AbstractFactory,包含创建形状和颜色对象的方法:
// AbstractFactory 接口
public interface AbstractFactory {
Shape createShape();
Color createColor();
}
然后定义具体的工厂类 ShapeFactory 和 ColorFactory,分别用于创建形状和颜色对象:
// ShapeFactory 工厂类
public class ShapeFactory implements AbstractFactory {
@Override
public Shape createShape() {
return new Circle();
}
@Override
public Color createColor() {
return new Red();
}
}
// ColorFactory 工厂类
public class ColorFactory implements AbstractFactory {
@Override
public Shape createShape() {
return new Rectangle();
}
@Override
public Color createColor() {
return new Blue();
}
}
最后,客户端代码可以通过抽象工厂来创建形状和颜色对象:
public class Client {
public static void main(String[] args) {
AbstractFactory shapeFactory = new ShapeFactory();
Shape shape = shapeFactory.createShape();
Color color = shapeFactory.createColor();
shape.draw();
color.fill();
AbstractFactory colorFactory = new ColorFactory();
Shape shape2 = colorFactory.createShape();
Color color2 = colorFactory.createColor();
shape2.draw();
color2.fill();
}
}
在上面的示例中,通过抽象工厂接口 AbstractFactory 来创建形状和颜色对象,客户端可以根据需要选择不同的具体工厂类来创建不同产品家族的对象。这样可以实现对象的创建和使用的解耦,提高了代码的灵活性和可维护性。