一、为什么需要工厂方法模式?
在软件开发中,对象创建与使用耦合会影响系统的灵活性和扩展性。以通知系统(支持邮件通知、短信通知和推送通知)为例 :直接实例化。
Notification email = new EmailNotification();
Notification sms = new SMSNotification();
Notification push = new PushNotification();
这种方式存在以下问题:
• 新增通知方式(如语音通知)时,需要修改客户端代码,违反了开闭原则。
• 客户端代码与具体通知类耦合过高,导致系统难以维护和扩展。
为了解决这些问题,引入工厂方法模式,将对象创建与使用分离,提高系统的灵活性与可扩展性。
二、什么是工厂方法模式?
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,其核心思想是:定义一个创建对象的接口,将具体对象的实例化过程延迟到子类中完成。
简单来说,工厂方法模式通过引入抽象工厂,将对象的创建逻辑封装起来,客户端只需要调用工厂方法,而无需关心对象如何创建。
工厂方法模式的优势包括:高扩展性、低耦合性,以及易于维护和测试。
三、工厂方法模式的实际案例
场景:同上文提到的 通知系统(支持邮件通知、短信通知和推送通知等)。
1. 抽象通知类
定义通知的统一接口,所有具体通知类都需实现它。
public abstract class Notification {
// 发送通知的抽象方法
public abstract void send(String message);
}
2. 具体通知类
分别实现邮件、短信和推送通知的发送逻辑。(注:如下3个通知类的逻辑类似)
// 邮件通知类
public class EmailNotification extends Notification {
@Override
public void send(String message) {
System.out.println("Sending email with message: " + message);
}
}
// 短信通知类
public class SMSNotification extends Notification {
@Override
public void send(String message) {
System.out.println("Sending SMS with message: " + message);
}
}
// 推送通知类
public class PushNotification extends Notification {
@Override
public void send(String message) {
System.out.println("Sending push notification with message: " + message);
}
}
3.抽象类:通知工厂基类
定义创建通知对象的工厂接口。
public abstract class NotificationFactory {
// 工厂方法,创建通知对象
public abstract Notification createNotification();
}
4. 具体工厂类
分别创建不同类型的通知对象。(注:如下3个通知工厂类的逻辑类似)
// 邮件通知工厂
public class EmailNotificationFactory extends NotificationFactory {
@Override
public Notification createNotification() {
return new EmailNotification();
}
}
// 通知工厂
public class SMSNotificationFactory extends NotificationFactory {
@Override
public Notification createNotification() {
return new SMSNotification();
}
}
// 推送通知工厂
public class PushNotificationFactory extends NotificationFactory {
@Override
public Notification createNotification() {
return new PushNotification();
}
}
5.客户端代码
通过具体工厂类来创建通知对象,并调用其方法。
public class Client {
public static void main(String[] args) {
// 通过工厂创建邮件通知
NotificationFactory emailFactory = new EmailNotificationFactory();
Notification email = emailFactory.createNotification();
email.send("Welcome to the system!");
// 通过工厂创建短信通知
NotificationFactory smsFactory = new SMSNotificationFactory();
Notification sms = smsFactory.createNotification();
sms.send("Your verification code is 123456.");
// 通过工厂创建推送通知
NotificationFactory pushFactory = new PushNotificationFactory();
Notification push = pushFactory.createNotification();
push.send("You have a new message.");
}
}
代码结构说明
• 抽象类 Notification:定义了发送通知的抽象方法send(),所有通知类都需实现它。
• 具体通知类:EmailNotification、SMSNotification和PushNotification 都继承自Notification,并实现具体的通知行为。
• 抽象工厂类 NotificationFactory:定义了创建通知对象的工厂方法createNotification()。
• 具体工厂类:EmailNotificationFactory、SMSNotificationFactory和PushNotificationFactory 继承自Noti-ficationFactory,分别负责创建各自类型的通知对象。
• 客户端:通过具体工厂类创建通知对象,实现对象创建与使用分离。
四、工厂方法模式的价值
1. 工厂方法模式 VS 简单工厂模式
工厂方法模式是简单工厂模式的进一步抽象,通过多态性将对象创建逻辑与客户端代码解耦。客户端依赖于抽象工厂接口,而非具体工厂类,从而降低了耦合度,符合开闭原则。
对比简单工厂模式:
• 简单工厂模式:工厂类集中管理产品对象创建,新增产品时需修改工厂类代码,违反开闭原则。
• 工厂方法模式:每新增一个产品,只需扩展新的产品类和对应的工厂类,符合开闭原则,但引入了额外的工厂类,增加了类的层级和开发工作量。
简单工厂模式和工厂方法模式的共同问题:
对于新增一个产品时,客户端代码仍需修改来指定具体工厂类的问题,可通过反射机制进一步优化。
2.工厂方法模式的优势
高扩展性:新增产品时,只需增加新的产品类和工厂类,无需修改现有工厂类代码。
低耦合性:产品对象创建与业务逻辑分离,职责单一,系统更易维护。
易测试性:每个工厂类和产品类都可以独立测试,修改时影响范围小,降低测试成本。
五、总结
工厂方法模式通过引入抽象工厂和具体工厂,实现了对象创建与使用的解耦,遵循了开闭原则和单一职责原则。
它提高了系统的扩展性、可维护性和可测试性,特别适用于大型、复杂项目。在开发中,工厂方法模式能够有效管理对象创建逻辑,保持系统稳定性。