Abstract Factory
抽象工厂模式与工厂方法模式虽然主要意图都是为了解决,接口选择问题。但在实现上,抽象工厂是一个中心工厂,创建其他工厂的模式。
以下是来自核心 Java 程序库的一些示例:
- javax.xml.parsers.DocumentBuilderFactory#newInstance()
- javax.xml.transform.TransformerFactory#newInstance()
- javax.xml.xpath.XPathFactory#newInstance()
识别方法: 我们可以通过方法来识别该模式——其会返回一个工厂对象。 接下来, 工厂将被用于创建特定的子组件。
抽象工厂结构模式
样例
跨平台的 UI 元素
Button 接口
package creational.abstractfactory.buttons;
/**
* This is the common interface for Button
*/
public interface IButton {
void paint();
}
实例化
package creational.abstractfactory.buttons;
/**
* All products families have the same varieties
*
* This is a MacOs variant of a Button
*/
public class MacOSButton implements IButton {
@Override
public void paint() {
System.out.println("You have created MacOSButton.");
}
}
package creational.abstractfactory.buttons;
/**
* This is anther variant of a button.
*/
public class WindowsButton implements IButton {
@Override
public void paint() {
System.out.println("You have created WindowsButton.");
}
}
checkbox 接口
package creational.abstractfactory.checkboxes;
/**
* Checkboxes is the second product family.
*/
public interface ICheckbox {
void paint();
}
实例化
package creational.abstractfactory.checkboxes;
/**
* This is a variant of a checkbox.
*/
public class MacOSCheckbox implements ICheckbox {
@Override
public void paint() {
System.out.println("You have created MacOSCheckbox");
}
}
package creational.abstractfactory.checkboxes;
/**
* This is another variant of a checkbox.
*/
public class WindowsCheckbox implements ICheckbox {
@Override
public void paint() {
System.out.println("You have created WindowsCheckbox.");
}
}
工厂接口
package creational.abstractfactory.factories;
import creational.abstractfactory.buttons.IButton;
import creational.abstractfactory.checkboxes.ICheckbox;
/**
* Abstract factory knows about all product types;
*/
public interface IGUIFactory {
IButton createButton();
ICheckbox createCheckbox();
}
实例化工厂
package creational.abstractfactory.factories;
import creational.abstractfactory.buttons.IButton;
import creational.abstractfactory.buttons.MacOSButton;
import creational.abstractfactory.checkboxes.ICheckbox;
import creational.abstractfactory.checkboxes.MacOSCheckbox;
/**
* 具体工厂
*/
public class MacOSFactory implements IGUIFactory {
@Override
public IButton createButton() {
return new MacOSButton();
}
@Override
public ICheckbox createCheckbox() {
return new MacOSCheckbox();
}
}
package creational.abstractfactory.factories;
import creational.abstractfactory.buttons.IButton;
import creational.abstractfactory.buttons.WindowsButton;
import creational.abstractfactory.checkboxes.ICheckbox;
import creational.abstractfactory.checkboxes.WindowsCheckbox;
/**
* Windows 具体工厂
*/
public class WindowsFactory implements IGUIFactory {
@Override
public IButton createButton() {
return new WindowsButton();
}
@Override
public ICheckbox createCheckbox() {
return new WindowsCheckbox();
}
}
调用demo
package creational.abstractfactory;
import creational.abstractfactory.buttons.IButton;
import creational.abstractfactory.checkboxes.ICheckbox;
import creational.abstractfactory.factories.IGUIFactory;
import creational.abstractfactory.factories.MacOSFactory;
import creational.abstractfactory.factories.WindowsFactory;
public class Demo {
public static void main(String[] args) {
IGUIFactory factory;
IButton button;
ICheckbox checkbox;
if (System.getProperty("os.name").equals("Windows 10")) {
factory = new WindowsFactory();
button = factory.createButton();
checkbox = factory.createCheckbox();
button.paint();
checkbox.paint();
} else {
factory = new MacOSFactory();
button = factory.createButton();
checkbox = factory.createCheckbox();
button.paint();
checkbox.paint();
}
}
}
抽象工厂模式适用场景
如果代码需要与多个不同系列的相关产品交互, 但是由于无法提前获取相关信息, 或者出于对未来扩展性的考虑, 你不希望代码基于产品的具体类进行构建, 在这种情况下,你可以使用抽象工厂。
抽象工厂为你提供了一个接口, 可用于创建每个系列产品的对象。 只要代码通过该接口创建对象, 那么你就不会生成与应用程序已生成的产品类型不一致的产品。
如果你有一个基于一组抽象方法的类, 且其主要功能因此变得不明确, 那么在这种情况下可以考虑使用抽象工厂模式。
在设计良好的程序中, 每个类仅负责一件事。 如果一个类与多种类型产品交互, 就可以考虑将工厂方法抽取到独立的工厂类或具备完整功能的抽象工厂类中。
实现方式
- 以不同的产品类型与产品变体为维度绘制矩阵。
- 为所有产品声明抽象产品接口。 然后让所有具体产品类实现这些接口。
- 声明抽象工厂接口, 并且在接口中为所有抽象产品提供一组构建方法。
- 为每种产品变体实现一个具体工厂类。
- 在应用程序中开发初始化代码。 该代码根据应用程序配置或当前环境, 对特定具体工厂类进行初始化。 然后将该工厂对象传递给所有需要创建产品的类。
- 找出代码中所有对产品构造函数的直接调用, 将其替换为对工厂对象中相应构建方法的调用。
抽象工厂模式优缺点
优点
- 你可以确保同一工厂生成的产品相互匹配。
- 你可以避免客户端和具体产品代码的耦合。
- 单一职责原则。 你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
- 开闭原则。 向应用程序中引入新产品变体时, 你无需修改客户端代码。
缺点
- 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。