一、什么是抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,++它提供了一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类++。这种模式允许客户端使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么,从而实现客户端与具体产品的解耦。
二、抽象工厂模式的角色
-
抽象产品族(Abstract Product):
- 这是一组相关的抽象类或接口,它们定义了可能被创建的对象的公共接口。
- 这些抽象产品通常包含在一个或多个产品等级结构中,每个产品等级结构代表一类产品。
-
具体产品(Concrete Product):
- 这些是抽象产品的实现类,它们提供了抽象产品接口的具体实现。
- 每个具体产品都是抽象产品接口的具体类,代表一个具体的对象。
-
抽象工厂(Abstract Factory):
- 这是一个接口,它声明了一组方法,用于创建一系列相关的抽象产品。
- 它不实现这些方法,而是将实现推迟到子类中。
- 抽象工厂定义了可以被创建的产品集合,但不定义具体如何创建这些产品。
-
具体工厂(Concrete Factory):
- 这些类实现了抽象工厂接口,并提供了具体工厂方法来创建具体的产品对象。
- 每个具体工厂都对应一个产品族,它负责创建该族中的具体产品。
- 具体工厂封装了具体产品的创建逻辑,客户端可以通过具体工厂来创建所需的产品,而无需知道具体的创建细节。
三、抽象工厂模式的典型应用场景
- 多系列产品创建: 当一个系统需要创建多个系列的相关产品,并且这些产品之间存在相互依赖关系时,使用抽象工厂模式可以确保客户端始终使用同一个系列的产品。
四、抽象工厂模式在Calendar中的应用
在抽象工厂模式中,Calendar
类可以被视为一个抽象工厂,它提供了创建各种具体日历实例的接口。GregorianCalendar
和 BuddhistCalendar
是 Calendar
类的具体实现,代表不同的日历系统。下面详细展开 Calendar
在抽象工厂模式中的应用,并给出包含 BuddhistCalendar
和 GregorianCalendar
的代码示例。
概念解释
-
抽象产品族(Abstract Product Family):在日历系统中,这可以是日期和时间的表示方式,包括年、月、日等。
-
抽象产品(Abstract Product) :
Calendar
类本身,它定义了所有具体日历类必须实现的接口,如getTime()
、setTime(Date date)
、get(int field)
等。 -
具体产品(Concrete Product) :
GregorianCalendar
和BuddhistCalendar
是具体的产品类,它们实现了Calendar
抽象类,并提供了特定日历系统的具体实现。 -
抽象工厂(Abstract Factory) :
Calendar
类也可以被视为一个抽象工厂,因为它的静态方法getInstance()
可以根据传入的Locale
参数返回不同的Calendar
实例。 -
具体工厂(Concrete Factory) :在这个模式中,具体工厂由 JDK 内部实现,它根据
Locale
参数决定实例化GregorianCalendar
还是BuddhistCalendar
。
java
//抽象工厂类
public abstract class Calendar {
public static class Builder {
public Builder setDate(int year, int month, int dayOfMonth) {
return setFields(YEAR, year, MONTH, month, DAY_OF_MONTH, dayOfMonth);
}
public Builder setTimeOfDay(int hourOfDay, int minute, int second) {
return setTimeOfDay(hourOfDay, minute, second, 0);
}
}
public static Calendar getInstance()
{
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}
public int getWeeksInWeekYear() {
throw new UnsupportedOperationException();
}
}
//具体工厂类
public class GregorianCalendar extends Calendar {
@Override
public int getWeeksInWeekYear() {
GregorianCalendar gc = getNormalizedCalendar();
int weekYear = gc.getWeekYear();
if (weekYear == gc.internalGet(YEAR)) {
return gc.getActualMaximum(WEEK_OF_YEAR);
}
// Use the 2nd week for calculating the max of WEEK_OF_YEAR
if (gc == this) {
gc = (GregorianCalendar) gc.clone();
}
gc.setWeekDate(weekYear, 2, internalGet(DAY_OF_WEEK));
return gc.getActualMaximum(WEEK_OF_YEAR);
}
}
//具体工厂类
public class BuddhistCalendar extends GregorianCalendar {
}
// 客户端
public class CalendarAbstractFactoryDemo {
public static void main(String[] args) {
// 创建一个默认的 GregorianCalendar 实例
Calendar defaultCalendar = Calendar.getInstance();
printCalendarInfo(defaultCalendar, "Default Calendar");
// 创建一个 BuddhistCalendar 实例,用于泰国
Locale thailandLocale = new Locale("th", "TH");
Calendar thaiCalendar = Calendar.getInstance(thailandLocale);
printCalendarInfo(thaiCalendar, "Thai Buddhist Calendar");
}
private static void printCalendarInfo(Calendar calendar, String calendarType) {
// 设置日期
calendar.setTime(new Date());
System.out.println(calendarType + " - Year: " + calendar.get(Calendar.YEAR));
System.out.println(calendarType + " - Month: " + calendar.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.ENGLISH));
System.out.println(calendarType + " - Day: " + calendar.get(Calendar.DAY_OF_MONTH));
System.out.println();
}
}
在这个示例中:
Calendar.getInstance()
方法根据提供的Locale
参数决定创建哪种具体的Calendar
实例。如果没有指定Locale
,它通常会创建一个GregorianCalendar
实例,这是大多数地区的默认日历系统。- 当我们传递泰国的
Locale
对象给Calendar.getInstance()
方法时,它返回一个BuddhistCalendar
实例,这是泰国使用的日历系统。 printCalendarInfo()
方法打印日历的详细信息,包括年、月、日。它展示了如何使用Calendar
实例来获取日期信息。
这个例子展示了 Calendar
类如何作为一个抽象工厂,根据不同的 Locale
参数创建不同的日历实例。这种方式使得客户端代码能够灵活地根据不同的需求创建适当的日历对象,而不需要了解具体的日历实现细节。这种设计符合抽象工厂模式的原则,提供了一个创建一系列相关或相互依赖对象的接口,而不需要指定它们具体的类。
五、简单工厂模式与复杂工厂模式的区别
简单工厂模式和抽象工厂模式都是创建型设计模式,用于创建对象,但它们在解决问题的范围和方式上存在明显差异:
简单工厂模式:
- 解决问题的范围:简单工厂模式主要用于创建单一类型的产品。它适用于场景中对象的创建逻辑相对简单,或者需要创建的对象种类较少的情况。
- 核心思想:简单工厂模式通过一个工厂类包含一个或多个方法,根据传入的参数来决定创建并返回哪种具体产品的实例。
抽象工厂模式:
- 解决问题的范围:抽象工厂模式用于创建多个产品族中相关或相互依赖的产品对象。它适用于场景中需要创建一系列相关或相互依赖的产品,且这些产品属于不同的产品等级结构。
- 核心思想:抽象工厂模式定义了一个接口,用于创建一系列相关的产品,而不需要指定它们的具体类。具体工厂类实现了这个接口,并提供了创建具体产品的方法。