1. 简单工厂模式
在了解工厂方法模式之前,有必要对“简单工厂”模式进行一定的了解,简单工厂模式是一种创建型设计模式,但并不属于23种设计模式之一,更多的是一种编程习惯。
简单工厂模式的核心思想是将产品的创建过程封装在一个工厂类中,把创建对象的流程集中在这个工厂类里面。
简单工厂模式包括三个主要角色,工厂类、抽象产品、具体产品,下面的图示则展示了工厂类的基本结构。
- 抽象产品,比如下图中的
Shape
接口,描述产品的通用行为。
- 具体产品: 实现抽象产品接口或继承抽象产品类,比如上面的
Circle
类和Square
类,具体产品通过简单工厂类的if-else
逻辑来实例化。
- 工厂类:负责创建产品,根据传递的不同参数创建不同的产品示例。
简单工厂类简化了客户端操作,客户端可以调用工厂方法来获取具体产品,而无需直接与具体产品类交互,降低了耦合,但是有一个很大的问题就是不够灵活,如果需要添加新的产品,就需要修改工厂类的代码。
2. 什么是工厂方法模式
工厂方法模式也是一种创建型设计模式,简单工厂模式只有一个工厂类,负责创建所有产品,如果要添加新的产品,通常需要修改工厂类的代码。而工厂方法模式引入了抽象工厂和具体工厂的概念,每个具体工厂只负责创建一个具体产品,添加新的产品只需要添加新的工厂类而无需修改原来的代码,这样就使得产品的生产更加灵活,支持扩展,符合开闭原则。
工厂方法模式分为以下几个角色:
- 抽象工厂:一个接口,包含一个抽象的工厂方法(用于创建产品对象)。
- 具体工厂:实现抽象工厂接口,创建具体的产品。
- 抽象产品:定义产品的接口。
- 具体产品:实现抽象产品接口,是工厂创建的对象。
实际上工厂方法模式也很好理解,就拿“手机Phone”这个产品举例,手机是一个抽象产品,小米手机、华为手机、苹果手机是具体的产品实现,而不同品牌的手机在各自的生产厂家生产。
3. 基本实现
根据上面的类图,我们可以写出工厂方法模式的基本实现。
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
| interface Shape { void draw(); }
class Circle implements Shape { @Override public void draw() { System.out.println("Circle"); } }
class Square implements Shape { @Override public void draw() { System.out.println("Square"); } }
interface ShapeFactory { Shape createShape(); }
class CircleFactory implements ShapeFactory { @Override public Shape createShape() { return new Circle(); } }
class SquareFactory implements ShapeFactory { @Override public Shape createShape() { return new Square(); } }
public class Client { public static void main(String[] args) { ShapeFactory circleFactory = new CircleFactory(); Shape circle = circleFactory.createShape(); circle.draw();
ShapeFactory squareFactory = new SquareFactory(); Shape square = squareFactory.createShape(); square.draw(); } }
|
4. 应用场景
工厂方法模式使得每个工厂类的职责单一,每个工厂只负责创建一种产品,当创建对象涉及一系列复杂的初始化逻辑,而这些逻辑在不同的子类中可能有所不同时,可以使用工厂方法模式将这些初始化逻辑封装在子类的工厂中。在现有的工具、库中,工厂方法模式也有广泛的应用,比如:
- Spring 框架中的 Bean 工厂:通过配置文件或注解,Spring 可以根据配置信息动态地创建和管理对象。
- JDBC 中的 Connection 工厂:在 Java 数据库连接中,
DriverManager
使用工厂方法模式来创建数据库连接。不同的数据库驱动(如 MySQL、PostgreSQL 等)都有对应的工厂来创建连接。
5. 举例说明
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 79 80 81 82 83 84 85 86 87 88
| import java.util.ArrayList; import java.util.List; import java.util.Scanner;
interface Block { void produce(); }
class CircleBlock implements Block { @Override public void produce() { System.out.println("Circle Block"); } }
class SquareBlock implements Block { @Override public void produce() { System.out.println("Square Block"); } }
interface BlockFactory { Block createBlock(); }
class CircleBlockFactory implements BlockFactory { @Override public Block createBlock() { return new CircleBlock(); } }
class SquareBlockFactory implements BlockFactory { @Override public Block createBlock() { return new SquareBlock(); } }
class BlockFactorySystem { private List<Block> blocks = new ArrayList<>();
public void produceBlocks(BlockFactory factory, int quantity) { for (int i = 0; i < quantity; i++) { Block block = factory.createBlock(); blocks.add(block); block.produce(); } }
public List<Block> getBlocks() { return blocks; } }
public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in);
BlockFactorySystem factorySystem = new BlockFactorySystem();
int productionCount = scanner.nextInt(); scanner.nextLine();
for (int i = 0; i < productionCount; i++) { String[] productionInfo = scanner.nextLine().split(" "); String blockType = productionInfo[0]; int quantity = Integer.parseInt(productionInfo[1]);
if (blockType.equals("Circle")) { factorySystem.produceBlocks(new CircleBlockFactory(), quantity); } else if (blockType.equals("Square")) { factorySystem.produceBlocks(new SquareBlockFactory(), quantity); } } } }
|