抽象工厂模式(学习笔记)
1. 意图
提供一个接口以提供一系列相关或相互依赖的对象,而无须知道指定它们的具体的类
2. 别名
Kit
3. 动机
- 在软件系统中经常面临着一系列相互依赖的对象的创建工作;同时,由于需求变化,往往存在更多系列对象的创建工作
- 如何绕过常规的对象创建方法(new),提供一种封装机制来避免客户程序和这种多系列具体对象创建工作的紧耦合
4. 适用性
- 一个系统独立于它的产品的创建、组合和表示
- 一个系统要由多个产品系列中的一个配置
- 要强调一系列相关产品对象的设计以便进行联合使用
- 提供一个产品类库,但是只想显示接口而不是实现
5. 结构
6. 效果
抽象工厂具有以下优点和缺点:
1) 分离了具体的类 客户通过它们的抽象对象接口操纵实例。产品的类名也在具体工厂的实现中被隔离,即它们不出现在客户代码中
2) 易于交换产品系列 抽象工厂创建了完整的产品系列,只需要改变具体工厂即可使用不同产品的配置
3) 利于产品的统一性 当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一系列中的对象
4) 难以支持新种类的产品 抽象工厂接口确定了可以被创建的产品集合。支持新种类的产品就需要扩展该工厂接口,这将设计抽象工厂类及其子类的改变
7. 代码实现
buttons: 第一个产品层次结构
Button.java
package abstract_factory; /** * @author GaoMing * @date 2021/7/17 - 15:37 * */ public interface Button { void paint(); }
MacOSButton.java
package abstract_factory;
/**
* @author GaoMing
* @date 2021/7/17 - 15:38
*/
public class MacOSButton implements Button{
@Override
public void paint(){
System.out.println("You have created MacOSButton.");
}
}
WindowsButton.java
package abstract_factory; /** * @author GaoMing * @date 2021/7/17 - 15:39 */ public class WindowsButton implements Button{ @Override public void paint(){ System.out.println("You have created WindowButton."); } }
Checkbox: 第二个产品结构
Checkbox.java
package abstract_factory; /** * @author GaoMing * @date 2021/7/17 - 15:40 */ public interface Checkbox { void paint(); }
MacOSCheckbox.java
package abstract_factory; /** * @author GaoMing * @date 2021/7/17 - 15:41 */ public class MacOSCheckbox implements Checkbox{ @Override public void paint(){ System.out.println("You have created MacOSCheckbox."); } }
WindowsCheckbox.java
package abstract_factory;
/**
* @author GaoMing
* @date 2021/7/17 - 15:42
*/
public class WindowsCheckbox implements Checkbox{
@Override
public void paint(){
System.out.println("You have created WindowCheckbox.");
}
}
Factories
GUIFactories.java: 抽象工厂
package abstract_factory.factories; import abstract_factory.Button; import abstract_factory.Checkbox; /** * @author GaoMing * @date 2021/7/17 - 15:43 */ public interface GUIFactory { Button createButton(); Checkbox createCheckbox(); }
MacOSFactory.java: 具体工厂 ( macOS)
package abstract_factory.factories; import abstract_factory.Button; import abstract_factory.Checkbox; import abstract_factory.MacOSButton; import abstract_factory.MacOSCheckbox; /** * @author GaoMing * @date 2021/7/17 - 15:46 */ public class MacOSFactory implements GUIFactory{ @Override public Button createButton(){ return new MacOSButton(); } @Override public Checkbox createCheckbox(){ return new MacOSCheckbox(); } }
WindowsFactory.java: 具体工厂 (Windows)
package abstract_factory.factories; import abstract_factory.Button; import abstract_factory.Checkbox; import abstract_factory.WindowsButton; import abstract_factory.WindowsCheckbox; /** * @author GaoMing * @date 2021/7/17 - 15:49 */ public class WindowsFactory implements GUIFactory{ @Override public Button createButton(){ return new WindowsButton(); } @Override public Checkbox createCheckbox(){ return new WindowsCheckbox(); } }
Application.java: 客户端代码
package abstract_factory; import abstract_factory.Button; import abstract_factory.Checkbox; import abstract_factory.factories.GUIFactory; /** * @author GaoMing * @date 2021/7/17 - 15:52 */ public class Application { private Button button; private Checkbox checkbox; public Application(GUIFactory factory){ button = factory.createButton(); checkbox = factory.createCheckbox(); } public void paint(){ button.paint(); checkbox.paint(); } }
Demo.java: 程序配置
package abstract_factory; import abstract_factory.factories.GUIFactory; import abstract_factory.factories.MacOSFactory; import abstract_factory.factories.WindowsFactory; import abstract_factory.Application; import java.util.Locale; /** * @author GaoMing * @date 2021/7/17 - 15:57 */ public class Demo { private static Application configureApplication(){ Application app; GUIFactory factory; String osName = System.getProperty("os.name").toLowerCase(); if(osName.contains("mac")){ factory = new MacOSFactory(); app = new Application(factory); }else{ factory = new WindowsFactory(); app = new Application(factory); } return app; } public static void main(String[] args){ Application app = configureApplication(); app.paint(); } }
运行结果
You create WindowsButton.
You created WindowsCheckbox.
8. 与其他模式的关系
- 一个应用中每个产品系列只需要一个ConcreteFactory的实例。可用Singleton实现
- 抽象工厂模式通常基于一组工厂方法, 但你也可以使用原型模式来生成这些类的方法
- Builder 重点关注如何分步生成复杂对象。 抽象工厂专门用于生产一系列相关对象。 抽象工厂会马上返回产品, 生成器则允许你在获取产品前执行一些额外构造步骤
- 当只需对客户端代码隐藏子系统创建对象的方式时, 你可以使用抽象工厂来代替外观模式
9. 已知应用
-
javax.xml.parsers.DocumentBuilderFactory#newInstance()
-
javax.xml.transform.TransformerFactory#newInstance()
-
javax.xml.xpath.XPathFactory#newInstance()