设计模式:抽象工厂 - 掌控多产品族的创建之道
一、什么是抽象工厂模式?
抽象工厂模式是一种创建型设计模式,提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。
核心思想
1.定义多个产品的抽象接口,统一管理具体产品和工厂的创建逻辑。
2.客户端通过抽象工厂接口获取对象,屏蔽具体实现,降低耦合度。
特点
1.适用于需要创建多个产品族的场景。
2.提高系统的一致性和扩展性,便于后期维护。
总结:抽象工厂模式通过定义一组抽象产品接口及其具体实现,将对象的创建与使用解耦,使系统便于扩展和维护。
二、抽象工厂模式 vs 工厂方法模式
在深入了解抽象工厂模式之前,先来看看它与工厂方法模式的相似点和不同点。
相似点
1.核心理念一致:
两者都通过工厂类封装对象的创建过程,避免直接实例化对象,从而提高代码的灵活性和可维护性。
2.关键要素相似:
两者均包含以下四个核心要素:抽象工厂、具体工厂、抽象产品、具体产品。
3.问题类似:
新增产品时,客户端代码仍需修改来指定具体工厂类。
不同点
1.抽象产品的数量
• 工厂方法模式:只有一个抽象产品类,每个具体工厂类只能创建一个具体产品实例。
• 抽象工厂模式:有多个抽象产品类,每个具体工厂类可以创建多个具体产品实例。
2.具体工厂的功能
• 工厂方法模式:每个具体工厂只能创建单一类型的具体产品实例。
• 抽象工厂模式:每个具体工厂可以创建多个相关的具体产品实例。
3.适用场景
• 工厂方法模式:适用于创建单一产品,且产品种类较简单。
• 抽象工厂模式:适用于创建一组相关联的产品,这些产品需保证一定的一致性。
总结
• 工厂方法模式:更简单,适合单一产品创建。
• 抽象工厂模式:功能更强大,适合创建多种相关产品的复杂场景。
三、抽象工厂模式的实际案例
场景
需要支持多种通知渠道(如邮件通知和短信通知),且每种渠道需要同时提供两种服务:普通通知和紧急通知。
没有使用设计模式的实现
public class NotificationService {
public void send(String type, String level, String message) {
if ("Email".equals(type)) {
if ("Normal".equals(level)) {
System.out.println("Sending Normal Email: " + message);
} else if ("Urgent".equals(level)) {
System.out.println("Sending Urgent Email: " + message);
}
} else if ("SMS".equals(type)) {
if ("Normal".equals(level)) {
System.out.println("Sending Normal SMS: " + message);
} else if ("Urgent".equals(level)) {
System.out.println("Sending Urgent SMS: " + message);
}
}
}
}
问题:
1.随着通知类型和通知级别的增加,if-else逻辑会变得非常复杂。
2.难以扩展,例如新增“推送通知”时,必须修改原有代码,违反开闭原则。
抽象工厂模式的实现
1.抽象产品类
定义两类产品接口:普通通知和紧急通知。
// 普通通知接口
public interface NormalNotification {
void send(String message);
}
// 紧急通知接口
public interface UrgentNotification {
void send(String message);
}
2.具体产品类
实现邮件通知和短信通知的具体逻辑。
// 邮件普通通知
public class EmailNormalNotification implements NormalNotification {
public void send(String message) {
System.out.println("Sending Normal Email: " + message);
}
}
// 邮件紧急通知
public class EmailUrgentNotification implements UrgentNotification {
public void send(String message) {
System.out.println("Sending Urgent Email: " + message);
}
}
// 短信普通通知
public class SMSNormalNotification implements NormalNotification {
public void send(String message) {
System.out.println("Sending Normal SMS: " + message);
}
}
// 短信紧急通知
public class SMSUrgentNotification implements UrgentNotification {
public void send(String message) {
System.out.println("Sending Urgent SMS: " + message);
}
}
3.抽象工厂类
定义工厂接口,用于创建普通通知和紧急通知的产品实例。
public interface NotificationFactory {
NormalNotification createNormalNotification();
UrgentNotification createUrgentNotification();
}
4.具体工厂类
分别实现邮件通知工厂和短信通知工厂。
// 邮件通知工厂:2类产品(普通通知和紧急通知)
public class EmailNotificationFactory implements NotificationFactory {
public NormalNotification createNormalNotification() {
return new EmailNormalNotification();
}
public UrgentNotification createUrgentNotification() {
return new EmailUrgentNotification();
}
}
// 短信通知工厂:2类产品(普通通知和紧急通知)
public class SMSNotificationFactory implements NotificationFactory {
public NormalNotification createNormalNotification() {
return new SMSNormalNotification();
}
public UrgentNotification createUrgentNotification() {
return new SMSUrgentNotification();
}
}
5.客户端代码
客户端通过抽象工厂动态选择具体工厂,并创建相应的产品对象。
public class Client {
public static void main(String[] args) {
// 使用邮件通知工厂
NotificationFactory emailFactory = new EmailNotificationFactory();
// 获取普通邮件通知
NormalNotification emailNormal = emailFactory.createNormalNotification();
// 获取紧急邮件通知
UrgentNotification emailUrgent = emailFactory.createUrgentNotification();
// 发送普通邮件通知
emailNormal.send("This is a normal email.");
// 发送紧急邮件通知
emailUrgent.send("This is an urgent email.");
// 使用短信通知工厂
NotificationFactory smsFactory = new SMSNotificationFactory();
// 获取普通短信通知
NormalNotification smsNormal = smsFactory.createNormalNotification();
// 获取紧急短信通知
UrgentNotification smsUrgent = smsFactory.createUrgentNotification();
// 发送普通短信通知
smsNormal.send("This is a normal SMS.");
// 发送紧急短信通知
smsUrgent.send("This is an urgent SMS.");
}
}
四、抽象工厂模式的价值
1.更强的扩展性
新增通知方式(如推送通知)时,只需添加新的工厂类和具体产品类,不修改已有的产品及工厂代码。
2.降低耦合度
客户端只依赖抽象接口,避免直接依赖具体的产品类和工厂类。
3.管理多个产品族
可同时管理多个产品(如普通通知和紧急通知等),保持系统设计的一致性。
4.易维护与测试
每个工厂和产品类可以独立测试,修改时影响范围更小,降低维护成本。
五、总结
抽象工厂模式在工厂方法模式的基础上,解决了单一产品创建的问题,支持多个产品族的创建,提升了系统的一致性、扩展性和可维护性。
在复杂项目中,抽象工厂模式可以有效管理对象创建逻辑,保持系统的稳定性和灵活性。