抽象工厂模式是一种创建型设计模式,它提供了一个接口,用于创建相关或依赖对象的家族,而无需指定具体类。
在这种模式中,客户端不关心对象是如何创建的,只需要知道每个工厂能够生产什么类型的对象即可。这种模式使得系统更加灵活,因为可以在运行时切换工厂以获得不同的对象组合。
下面我们通过一个简单的示例来了解抽象工厂模式的具体实现方式。假设我们要开发一款模拟游戏,该游戏支持多种操作系统,包括Windows、macOS和Linux。为了在不同的操作系统上实现相同的功能,我们需要使用不同的UI控件,例如按钮、文本框和标签等。因此,我们可以通过抽象工厂模式来创建UI组件的不同家族,如Windows UI家族、macOS UI家族和Linux UI家族。
首先,我们需要定义UI控件的基本接口,例如Button、TextBox和Label:
interface Button {
void paint();
}
interface TextBox {
void paint();
}
interface Label {
void paint();
}
然后,我们定义不同操作系统的UI组件家族:
interface GUIFactory {
Button createButton();
TextBox createTextBox();
Label createLabel();
}
class WindowsFactory implements GUIFactory {
public Button createButton() {
return new WindowsButton();
}
public TextBox createTextBox() {
return new WindowsTextBox();
}
public Label createLabel() {
return new WindowsLabel();
}
}
class macOSFactory implements GUIFactory {
public Button createButton() {
return new macOSButton();
}
public TextBox createTextBox() {
return new macOSTextBox();
}
public Label createLabel() {
return new macOSLabel();
}
}
class LinuxFactory implements GUIFactory {
public Button createButton() {
return new LinuxButton();
}
public TextBox createTextBox() {
return new LinuxTextBox();
}
public Label createLabel() {
return new LinuxLabel();
}
}
接下来,我们定义具体的UI控件类:
class WindowsButton implements Button {
public void paint() {
System.out.println("WindowsButton");
}
}
class WindowsTextBox implements TextBox {
public void paint() {
System.out.println("WindowsTextBox");
}
}
class WindowsLabel implements Label {
public void paint() {
System.out.println("WindowsLabel");
}
}
class macOSButton implements Button {
public void paint() {
System.out.println("macOSButton");
}
}
class macOSTextBox implements TextBox {
public void paint() {
System.out.println("macOSTextBox");
}
}
class macOSLabel implements Label {
public void paint() {
System.out.println("macOSLabel");
}
}
class LinuxButton implements Button {
public void paint() {
System.out.println("LinuxButton");
}
}
class LinuxTextBox implements TextBox {
public void paint() {
System.out.println("LinuxTextBox");
}
}
class LinuxLabel implements Label {
public void paint() {
System.out.println("LinuxLabel");
}
}
最后,我们在客户端代码中,我们可以使用不同的工厂对象来创建不同操作系统下的UI组件家族:
public class Client {
public static void main(String[] args) {
GUIFactory factory = new WindowsFactory();
Button button = factory.createButton();
TextBox textBox = factory.createTextBox();
Label label = factory.createLabel();
button.paint();
textBox.paint();
label.paint();
factory = new macOSFactory();
button = factory.createButton();
textBox = factory.createTextBox();
label = factory.createLabel();
button.paint();
textBox.paint();
label.paint();
factory = new LinuxFactory();
button = factory.createButton();
textBox = factory.createTextBox();
label = factory.createLabel();
button.paint();
textBox.paint();
label.paint();
}
}
运行客户端代码,将会得到不同操作系统下的UI组件输出结果。
在Android开发中,抽象工厂模式可以用于创建不同风格或主题的UI控件。例如,在实现日间模式和夜间模式时,我们可以定义两个UI组件家族,分别对应不同的主题样式。然后,我们可以根据当前的主题样式来使用不同的工厂对象来创建相应的UI组件。
在第三方开源代码中,抽象工厂模式也经常被使用。例如,Retrofit是一个非常流行的网络库,它允许开发者使用不同的转换器工厂来创建网络请求响应的转换器。转换器工厂可以根据不同的数据类型来创建相应的转换器。这样,开发者可以根据自己的需求来选择不同的转换器工厂,以便在不同的网络请求场景下使用不同的转换器。
在Retrofit中,抽象工厂模式被应用于网络请求响应的转换器。Retrofit允许开发者通过设置不同的转换器工厂来支持不同的数据格式,例如JSON、XML等等。转换器工厂是一个抽象工厂,它定义了一个创建转换器的工厂方法。
以下是Retrofit中的转换器工厂抽象类:
public interface Converter.Factory {
Converter, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit);
Converter responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit);
}
在这个抽象类中,我们定义了两个工厂方法,分别用于创建请求体的转换器和响应体的转换器。具体的转换器工厂需要实现这两个工厂方法,以便创建相应的转换器对象。
以下是一个示例的JSON转换器工厂:
public final class GsonConverterFactory extends Converter.Factory {
private final Gson gson;
private GsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
public static GsonConverterFactory create() {
return create(new Gson());
}
public static GsonConverterFactory create(Gson gson) {
return new GsonConverterFactory(gson);
}
@Override
public Converter, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
@Override public Converter responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
}
在这个转换器工厂中,我们使用Gson库来创建JSON格式的转换器。该转换器工厂实现了Converter.Factory抽象类中的两个工厂方法,并返回了相应的JSON请求体和响应体转换器对象。
在使用Retrofit时,我们可以通过以下方式来使用这个JSON转换器工厂:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
在这个示例中,我们通过addConverterFactory()方法向Retrofit实例中添加了一个JSON转换器工厂。这样,Retrofit将会使用该工厂来创建JSON格式的请求体和响应体转换器对象,以便在网络请求中进行数据的转换。