王国内部最大的编程学院——设计模式学院,迎来了一群新学员。学院的校长,是一位经验丰富的程序员长者,他决定给新学员们讲述一个关于工厂方法模式的故事。
在王国的边境,有一个被称为“对象工厂”的地方。这个工厂是整个王国的骄傲,因为它能够根据需求制造出各种神奇的对象。工厂的秘密在于一种叫做“工厂方法”的神奇魔法,这种魔法允许工厂提供一个创建对象的接口,但具体要生成什么对象,则由子类的魔法师来决定。
在工厂的核心区域,有两个出色的魔法师:一种是魔法武器大师,另一种是魔法药水大师。每当王国需要新的武器或者药水时,这两个魔法师便会施展他们的工厂方法魔法,制造出对应的魔法物品。
有一次,邻国的巨龙苏醒,开始威胁整个王国的安全。王国的骑士们急需强力的魔法武器和治疗药水来对抗巨龙。国王召集了工厂中的两位大师,请求他们提供帮助。
首先,魔法武器大师通过他的工厂方法魔法,制造出了一把把充满力量的魔法剑。这些剑不仅锋利无比,还能发出耀眼的光芒,令敌人畏惧。
接着,魔法药水大师也施展了他的工厂方法魔法,制造出了一瓶瓶治愈药水。这些药水能够迅速治愈骑士们在战斗中的伤口,让他们保持战斗力。
每当王国面临不同的挑战时,魔法师们就会根据具体需求,运用工厂方法魔法制造出相应的物品。正是因为这个神奇的工厂方法魔法,王国才能屡次化险为夷,保卫了家园的安宁。
工厂方法模式 (Factory Method Pattern)
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,提供了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式让类的实例化推迟到子类。这样,客户端代码将依赖于具体子类的实现,而不是直接依赖于具体的对象。
适用场景
-
代码需要处理不同类型的对象,但不希望将对象的创建逻辑耦合到代码中:
- 比如,在处理不同数据库类型(如 MySQL、PostgreSQL)时,可以使用工厂方法模式来创建数据库连接对象,而不需要在客户端代码中直接引用具体的数据库类。
-
代码中涉及复杂的对象创建过程:
- 如果对象的创建过程很复杂,包括许多步骤和配置,工厂方法模式可以将创建逻辑集中在一个地方,简化客户端代码。
-
客户端代码不应依赖于具体类来创建对象:
- 工厂方法模式使客户端代码依赖于抽象类或接口,从而提高代码的灵活性和可扩展性。
实现示例(Java)
下面是一个使用工厂方法模式的示例,展示如何创建不同类型的日志记录器(如文件日志记录器和数据库日志记录器):
1. 定义产品接口或抽象类
public interface Logger {
void log(String message);
}
2. 具体产品类实现接口或继承抽象类
public class FileLogger implements Logger {
@Override
public void log(String message) {
System.out.println("File logger: " + message);
}
}
public class DatabaseLogger implements Logger {
@Override
public void log(String message) {
System.out.println("Database logger: " + message);
}
}
3. 定义工厂方法的抽象类
public abstract class LoggerFactory {
public abstract Logger createLogger();
public void log(String message) {
Logger logger = createLogger();
logger.log(message);
}
}
4. 具体工厂类实现工厂方法
public class FileLoggerFactory extends LoggerFactory {
@Override
public Logger createLogger() {
return new FileLogger();
}
}
public class DatabaseLoggerFactory extends LoggerFactory {
@Override
public Logger createLogger() {
return new DatabaseLogger();
}
}
5. 客户端代码
public class Main {
public static void main(String[] args) {
LoggerFactory factory;
Logger logger;
// 使用文件日志记录器
factory = new FileLoggerFactory();
factory.log("This is a file log message.");
// 使用数据库日志记录器
factory = new DatabaseLoggerFactory();
factory.log("This is a database log message.");
}
}
工厂方法模式的优点
-
代码解耦:
- 客户端代码依赖于抽象产品接口或抽象工厂,而不是具体的产品类,从而实现了代码的解耦。
-
提高灵活性:
- 新的具体产品可以通过实现产品接口并创建相应的具体工厂类来添加,而无需修改现有代码。
-
单一职责原则:
- 将对象创建的责任委派给具体工厂类,符合单一职责原则。
工厂方法模式的缺点
-
类的数量增加:
- 每添加一种新的产品类型,都需要创建一个具体产品类和相应的具体工厂类,可能会导致类的数量增加。
-
实现复杂:
- 工厂方法模式可能会使代码结构变得复杂,特别是在存在多个产品层次结构时。
总结
工厂方法模式通过将对象的创建过程封装在工厂方法中,实现了客户端代码与具体产品类的解耦。它适用于对象创建过程复杂、多种类型的对象创建等场景,有助于提高代码的灵活性和可维护性。