1.定义
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它提供了一种创建对象的接口,而不是通过具体类来实例化对象。工厂方法模式的主要作用是让子类决定实例化哪一个类,从而实现对象创建的延迟到具体子类中进行。
2.主要作用
作用就是使设计更加灵活和可扩展。通过这种方式,父类无需知道具体要创建的对象是哪一种,这样就提高了系统的可扩展性和可维护性(符合开闭原则)一切优秀的模式都向设计原则看齐。
3.解决的问题
说到解决的问题,这里就不得不提下简单工厂模式了,什么?你不知道简单工厂模式是什么,没关系,先来看下定义:
简单工厂模式是一种创建型模式,它定义了一个工厂类,该类包含一个方法,根据给定的参数来返回不同类的实例。
客户端通过向工厂类传递参数来获取所需的具体对象实例,而不需要直接实例化对象。
包含角色:
-
工厂类(Factory)
:负责根据客户端的请求创建相应的对象。 -
产品类(Product)
:被创建的对象的基类或接口。具体的产品类是工厂类所创建的对象类型。 -
具体产品类(Concrete Product)
:实现了产品接口的具体对象类,由工厂类根据客户端的需求创建和返回。
UML类图:
代码示例:
public class LoggerFactory {
public static Logger createLogger(String logType) {
if ("Console".equals(logType)) {
return new ConsoleLogger();
} else if ("File".equals(logType)) {
return new FileLogger();
} else if ("Remote".equals(logType)) {
return new RemoteLogger();
} else {
throw new IllegalArgumentException("Unsupported log type");
}
}
}
通过 LoggerFactory.createLogger("Console")
、LoggerFactory.createLogger("File")
或者 LoggerFactory.createLogger("Remote")
来获取不同类型的日志记录器,这种方式就是简单工厂模式,熟不熟悉,在你的项目中是不是也使用过这种模式呢,由于不难理解所以称为简单。
简单是简单,当然他也有一些弊端,如果上面示例代码中 Logger 抽象类中只有打印一个方法,后续需要新增保存日志,过滤日志… 问题就暴露出来了,简单来说就是 简单工厂模式违反了开闭原则,即对扩展开放,对修改关闭。
工厂方法模式解决了简单工厂模式的哪些问题?
- 开闭原则:工厂方法模式遵循开闭原则,通过定义抽象工厂类和具体工厂类的继承关系,新增产品时只需增加具体工厂类和产品类,而无需修改现有代码,降低了系统的耦合性。
- 扩展性:工厂方法模式支持更多的灵活性,每个具体的工厂类只负责创建对应的产品,符合单一职责原则,代码更加清晰和可维护。
- 维护性:由于工厂方法模式将对象的创建延迟到子类中,避免了简单工厂模式中工厂类集中所有产品创建逻辑的问题,使代码结构更加清晰和可扩展。
简单来说,就是解决了简单工厂模式中集中创建逻辑和不符合开闭原则的问题,提高了代码的灵活性和可维护性。
4.模式原理
包含角色:
产品(Product)
:定义产品的接口。具体产品(ConcreteProduct)
:实现产品接口的具体类。工厂(Factory)
:定义创建产品对象的接口。具体工厂(ConcreteFactory)
:实现创建产品对象的具体类。
UML类图:
// 定义产品接口
public interface Product {
String operation();
}
// 定义具体产品类
public class ConcreteProductA implements Product {
@Override
public String operation() {
return "产品A";
}
}
public class ConcreteProductB implements Product {
@Override
public String operation() {
return "产品B";
}
}
// 定义工厂接口
public abstract class Creator {
// 工厂方法
public abstract Product factoryMethod();
// 其它操作方法
public String someOperation() {
Product product = factoryMethod();
return product.operation();
}
}
// 定义具体工厂类
public class ConcreteCreatorA extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductA();
}
}
public class ConcreteCreatorB extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductB();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
clientCode(new ConcreteCreatorA());
clientCode(new ConcreteCreatorB());
}
public static void clientCode(Creator creator) {
System.out.println("Client: " + creator.someOperation());
}
}
打印:
Client: 产品A
Client: 产品B
相较简单工厂模式 增加了一个具体工厂角色,每增加一个具体产品,需要同时增加一个具体工厂类。所以说各有优缺点吧。
4.优缺点
优点:
- 遵循开闭原则:可以在引入新产品时不修改现有代码。
- 遵循单一职责原则:将产品对象的创建逻辑封装在工厂类中。
- 减少代码耦合:客户端不直接依赖于具体类,只依赖于抽象产品和工厂接口(符合依赖倒置原则)。.
缺点:
- 增加代码复杂性:每增加一个具体产品,需要同时增加一个具体工厂类。
- 类的数量增加:每个具体产品都需要一个对应的具体工厂,会导致类的数量增加。
5.应用场景
- 需要创建复杂对象:当对象的创建过程比较复杂,且需要多步操作时。
- 产品种类多且类型不确定:当系统中需要创建的产品种类较多且类型在运行时才确定时。
- 需要对创建过程进行控制:当需要对对象的创建过程进行控制,并且希望将控制逻辑封装起来时。
emm… 其实还是简单工厂模式 应用场景更广泛些,毕竟简单好用🤭
总结比较:
- 简单工厂模式适合于对象类型较少且不经常变化的场景,代码较为简单,但不符合开闭原则,难以扩展新的产品类型。
- 工厂方法模式更加符合开闭原则,通过增加新的具体工厂和具体产品类来扩展系统功能,但会增加系统中类的个数和复杂度。
6.总结
工厂模式解决了简单工厂模式中集中创建逻辑和不符合开闭原则的问题,但同时自身也有一些弊端,但通过合理应用工厂方法模式,在特定的场景可以有效地提高系统的可维护性和扩展性。
设计模式没有最好的,只有最适合的,大家在选用时,要权衡利弊,避免过度设计!