概念
旨在定义一个用于创建对象的接口,但将具体的实例化工作放到子类中去完成。换句话说,工厂方法模式通过让子类决定实例化哪个具体类,从而实现了对象创建的灵活性和可扩展性。
用通俗的话来说就是工厂方法模式就像是一个“定制工厂”,告诉它我们的需求,它根据需求提供合适的产品,而不需要我们关心具体的生产过程
应用场景
工厂方法模式适用于需要创建多种同类但不同类型的具体对象,且具体创建哪种对象需在运行时根据条件动态决定,同时希望将对象的创建逻辑封装起来,使调用方仅依赖抽象接口而不感知具体类,并支持未来轻松扩展新类型而不修改客户端代码的场景。

基本结构

1)抽象产品(Product):定义产品的公共接口,是所有具体产品的父类
2)具体产品(ConcreteProduct):实现了抽象产品接口,表示某种具体的产品
3)抽象工厂(Factory):定义了一个返回产品对象的方法(一般是一个抽象方法)
4)具体工厂(ConcreteFactory):实现了抽象工厂中的创建产品的方法,生成具体的产品实例
代码实现
以 “消息通知系统” 为例,实现可以快速创建并发送消息对象
1)定义抽象产品接口
public interface Message {
void send(String to, String content);
}
2)定义多个具体产品
每个类都实现了 Message 接口,表示各自的发送方式
public class SmsMessage implements Message {
@Override
public void send(String to, String content) {
System.out.println("发送短信给 " + to + ",内容:" + content);
}
}
public class EmailMessage implements Message {
@Override
public void send(String to, String content) {
System.out.println("发送邮件给 " + to + ",内容:" + content);
}
}
public class InAppMessage implements Message {
@Override
public void send(String to, String content) {
System.out.println("发送站内信给 " + to + ",内容:" + content);
}
}
3)定义抽象工厂接口
这是抽象工厂的核心部分,它规定了工厂要提供的“产品生产线”接口
public interface MessageFactory {
Message createMessage();
}
4)定义多个具体工厂
每个工厂只负责创建一种消息对象,根据业务编写具体实现
public class SmsMessageFactory implements MessageFactory {
@Override
public Message createMessage() {
return new SmsMessage();
}
}
public class EmailMessageFactory implements MessageFactory {
@Override
public Message createMessage() {
return new EmailMessage();
}
}
public class InAppMessageFactory implements MessageFactory {
@Override
public Message createMessage() {
return new InAppMessage();
}
}
5)service层
使用的是工厂接口和产品接口而不是具体实现
public class NotificationService {
private final MessageFactory messageFactory;
public NotificationService(MessageFactory factory) {
this.messageFactory = factory;
}
public void notifyUser(String to, String content) {
Message message = messageFactory.createMessage();
message.send(to, content);
}
}
6)使用
在使用时使用指定工厂实现工厂接口即可,不需要操作或了解具体产品
public class Main {
public static void main(String[] args) {
MessageFactory factory = new SmsMessageFactory();
NotificationService service = new NotificationService(factory);
service.notifyUser("123456789", "您的验证码是 123456");
}
}
优缺点
优点
1)解耦对象创建和使用
调用方不用关心如何创建对象,只负责使用。如果后续创建对象的逻辑变了,也不用修改业务逻辑
2)符合开闭原则,易于扩展
当需要新增一个产品时,只需要新增一个对应的工厂类就行,原来的代码不用动
缺点
1)类的数量会增多
每新增一种产品,通常就要新增一个对应的工厂类。产品多了之后,工厂类也多,项目结构可能会显得臃肿。
