Abstract Factory Pattern
1. 什么是抽象工厂模式
抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形式。
在抽象工厂模式中,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品,这些产品构成了一个产品类别。
抽象工厂模式又称为Kit模式,它是一种对象创建型模式。
抽象工厂模式为创建一组对象提供了一种解决方案。与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品。
**抽象工厂模式与工厂方法模式最大的区别在于,**工厂方法模式针对的是一个产品类别,而抽象工厂模式需要面对多个产品类别,一个具体工厂可以负责多个不同产品类别中的产品对象的创建。
当一个具体工厂可以创建出分属于不同产品类别的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、更有效率。 极大减少了系统中类的个数。
2. 抽象工厂模式相关概念
2.1 产品等级结构
产品等级结构即产品的继承结构,即是一个类别的产品产品。
如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
2.2 产品族
产品族是指由同一个工厂生产的,不同类别的一组产品。
3. 抽象工厂模式类角色解析
抽象工厂模式结构图:
- **AbstractFactory(抽象工厂):**它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。它可以是接口,也可以是抽象类或者具体类。
- ConcreteFactory(具体工厂): 它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品类别中。
- **AbstractProduct(抽象产品):**它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
- **ConcreteProduct(具体产品):**它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。
4. 抽象工厂模式优缺点
优点:
- 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。
- 能够保证客户端始终只使用同一个产品族中的对象。(产品族约束)
- 调用者只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
缺点:
- 增加新的产品类别很麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。需要设计时就考虑好。
5. 实操感想
-
当系统所提供的工厂生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构、属于不同类型的具体产品时就可以使用抽象工厂模式。
步骤: -
首先抽象产品类别,然后写各个产品类别实例
-
创建抽象工厂,声明一组用于创建一族产品的方法
-
分别创建各个具体工厂,生成不同产品族产品实例
-
大量的重复代码,理解了Dagger2 直接使用opt生成代码。
6. 代码示例
示例代码在GitHub上: Abstract Factory
多种皮肤的各个控件样式:
//Button控件样式
public interface Button {
void display();
}
//Spring风格
public class ButtonSpring implements Button {
@Override public void display() {
System.out.println("Spring风格Button");
}
}
//Summer风格
public class ButtonSummer implements Button {
@Override public void display() {
System.out.println("Summer风格Button");
}
}
//CheckBox控件风格
public interface CheckBox {
void display();
}
public class CheckBoxSpring implements CheckBox {
@Override public void display() {
System.out.println("Spring风格CheckBox");
}
}
public class CheckBoxSummer implements CheckBox {
@Override public void display() {
System.out.println("Summber风格CheckBox");
}
}
//TextArea控件
public interface TextArea {
void display();
}
public class TextAreaSpring implements TextArea{
@Override public void display() {
System.out.println("Spring风格TextArea");
}
}
public class TextAreaSummmer implements TextArea {
@Override public void display() {
System.out.println("Summer风格TextArea");
}
}
/*
声明一组用于创建一族(一系列)产品的方法,每一个方法对应一种产品。
*/
public interface SkinFactory {
Button createButton();
CheckBox createCheckBox();
TextArea createTextArea();
}
//Spring风格工厂具体类
public class SKinFactorySpring implements SkinFactory {
@Override public Button createButton() {
return new ButtonSpring();
}
@Override public CheckBox createCheckBox() {
return new CheckBoxSpring();
}
@Override public TextArea createTextArea() {
return new TextAreaSpring();
}
}
//Summer风格工厂具体类
public class SkinFactorySummer implements SkinFactory {
@Override public Button createButton() {
return new ButtonSummer();
}
@Override public CheckBox createCheckBox() {
return new CheckBoxSummer();
}
@Override public TextArea createTextArea() {
return new TextAreaSummmer();
}
}
/*
测试类
可以看出,新增加一个产品族(皮肤风格)很方便,但新增加一个产品类别(控件)很复杂,到处修改代码。
*/
public class MainClass {
public static void main(String[] args) {
//SkinFactory sKinFactory = new SKinFactorySpring();
SkinFactory sKinFactory = new SkinFactorySummer();
Button button = sKinFactory.createButton();
CheckBox checkBox = sKinFactory.createCheckBox();
TextArea textArea = sKinFactory.createTextArea();
button.display();
checkBox.display();
textArea.display();
}
}