设计模式学习-抽象工厂模式

1.定义

提供接口,创建一系列相关或独立的对象,而不指定这些对象的具体类。

2.类图

3.代码示例

 1 package com.zhaoyangwoo.abstractfactory;
 2 
 3 /**
 4  * Created by john on 16/5/2.
 5  * @author wuzhaoyang
 6  * <p>
 7  *      抽象工厂:多个抽象产品类,派生出多个具体产品类;一个抽象工厂类,派生出多个具体工厂类;每个具体工厂类可创建多个具体产品类的实例。
 8  *      即提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们的具体的类。“一对多”的关系。
 9  * </p>
10  */
11 public class AbstractFactory {
12 
13     public static void main(String[] args) {
14         Factory factory1= new Factory1();
15         ProductA productA1 = factory1.createProductA();
16         ProductB productB1 = factory1.createProductB();
17         productA1.getName();
18         productB1.getBrand();
19 
20         Factory factory2= new Factory2();
21         ProductA productA2 = factory2.createProductA();
22         ProductB productB2 = factory2.createProductB();
23         productA2.getName();
24         productB2.getBrand();
25 
26     }
27 }
28 
29 
30 interface ProductA{
31     void getName();
32 }
33 
34 interface ProductB{
35     void getBrand();
36 }
37 
38 interface Factory{
39     ProductA createProductA();
40     ProductB createProductB();
41 }
42 
43 class ProductA1 implements ProductA{
44 
45     @Override
46     public void getName() {
47         System.out.println("i'm productA1");
48     }
49 }
50 
51 class ProductA2 implements ProductA{
52 
53     @Override
54     public void getName() {
55         System.out.println("i'm productA2");
56     }
57 }
58 
59 class ProductB1 implements ProductB{
60 
61     @Override
62     public void getBrand() {
63         System.out.println("i'm productB1");
64     }
65 }
66 
67 class ProductB2 implements ProductB{
68 
69     @Override
70     public void getBrand() {
71         System.out.println("i'm productB2");
72     }
73 }
74 
75 class Factory1 implements Factory{
76 
77     @Override
78     public ProductA createProductA() {
79         return new ProductA1();
80     }
81 
82     @Override
83     public ProductB createProductB() {
84         return new ProductB1();
85     }
86 }
87 
88 class Factory2 implements Factory{
89 
90     @Override
91     public ProductA createProductA() {
92         return new ProductA2();
93     }
94 
95     @Override
96     public ProductB createProductB() {
97         return new ProductB2();
98     }
99 }

4.应用场景举例

  • 创建复杂对象,隔离对象创建的具体过程
  • 客户端不需要知道具体产品类的类名,只需要知道所对应的具体工厂即可,具体的产品对象由具体工厂类创建; 

5.JDK源码中的模式实现

  为响应《设计模式-工厂模式》的思考1,不打算区分工厂方法和抽象工厂的实现。但是为了更好的理解,我们看javax.xml.transform.TransformerFactory的源码实现。

抽象工厂角色:

 1 package javax.xml.transform;
 2 
 3 /**
 4  * 我们看作者的注释明确写到,这个"abstractFactory"是用来创建Transformer和Templates两个产品族"product"
 5  * 
 6  * 
 7  * <p>A TransformerFactory instance can be used to create
 8  * {@link javax.xml.transform.Transformer} and
 9  * {@link javax.xml.transform.Templates} objects.</p>
10  *
11  */
12 public abstract class TransformerFactory {
13 
14     /**
15      * Default constructor is protected on purpose.
16      */
17     protected TransformerFactory() { }
18 
19 
20     ...
21     
22     public abstract Transformer newTransformer(Source source)
23             throws TransformerConfigurationException;
24 
25 
26 
27     public abstract Templates newTemplates(Source source)
28             throws TransformerConfigurationException;
29 
30     ...
31 
32 }
View Code

抽象产品角色:

 1 //两个抽象产品,构成产品族
 2 public abstract class Transformer {
 3 
 4     /**
 5      * Default constructor is protected on purpose.
 6      */
 7     protected Transformer() { }
 8 
 9      ...
10 }
11 
12 public interface Templates {
13 
14     ...
15 
16     Transformer newTransformer() throws TransformerConfigurationException;
17 
18     ...
19 }
View Code

具体工厂角色:

 1 public class TransformerFactoryImpl
 2         extends SAXTransformerFactory implements SourceLoader, ErrorListener
 3 {
 4 
 5     @Override
 6     public Transformer newTransformer()
 7             throws TransformerConfigurationException
 8     {
 9         TransformerImpl result = new TransformerImpl(new Properties(),
10                 _indentNumber, this);
11         if (_uriResolver != null) {
12             result.setURIResolver(_uriResolver);
13         }
14 
15         if (!_isNotSecureProcessing) {
16             result.setSecureProcessing(true);
17         }
18         return result;
19     }
20 
21     @Override
22     public Templates newTemplates(Source source)
23             throws TransformerConfigurationException
24     {
25         // If the _useClasspath attribute is true, try to load the translet from
26         // the CLASSPATH and create a template object using the loaded
27         // translet.
28         if (_useClasspath) {
29             String transletName = getTransletBaseName(source);
30 
31             if (_packageName != null)
32                 transletName = _packageName + "." + transletName;
33 
34             try {
35                 final Class clazz = ObjectFactory.findProviderClass(transletName, true);
36                 resetTransientAttributes();
37 
38                 return new TemplatesImpl(new Class[]{clazz}, transletName, null, _indentNumber, this);
39             }
40             catch (ClassNotFoundException cnfe) {
41                 ErrorMsg err = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, transletName);
42                 throw new TransformerConfigurationException(err.toString());
43             }
44             catch (Exception e) {
45                 ErrorMsg err = new ErrorMsg(
46                         new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)
47                                 + e.getMessage());
48                 throw new TransformerConfigurationException(err.toString());
49             }
50         }
51         ...
52 
53         return new TemplatesImpl(bytecodes, transletName,
54                 xsltc.getOutputProperties(), _indentNumber, this);
55     }
56 
57 
58 }
View Code

具体产品角色:

1 public final class TransformerImpl extends Transformer
2     implements DOMCache, ErrorListener
3 {
4 ...
5 }
6 public final class TemplatesImpl implements Templates, Serializable {
7 ...
8 }
View Code

6.思考

  • 抽象工厂最大的特点在哪里?
  最明显的在于扩展产品等级(具体工厂)很容易,但扩展产品族(具体产品)很难。由本文的代码实现可以看出,如果我这个时候给工厂添加新任务,生产ProductC,那需要怎么做?首先我必须修改Factory类添加
createProductC():ProductC 方法,另外最麻烦的是所有实现Factory的工厂都必须修改实现该方法。但是如果我需要Factory3来生产另一质量等级的ProductA3和ProductB3,只需要添加一个Factory3实现即可。
  • javax.xml.xpath.XPathFactory和javax.xml.parsers.DocumentBuilderFactory运用的是抽象工厂?

         首先我还是要声明一点,不管你用的是抽象工厂也好还是工厂方式也罢,本质上都是一样的,通过工厂封装产品生产的具体过程,客户端只需给出需要的产品,无需关心生产过程。

         其次抽象工厂和工厂方法唯一的区别就是是否构成产品族。

   这两个类的产品族有点变异,我们拿javax.xml.xpath.XPathFactory 举例,它的产品族包含两个产品:

    1. public static XPathFactory newInstance();
    2. public abstract XPath newXPath();
    其中一个产品不能是自己吗?有疑问的请移步《设计模式-工厂模式》的思考问题2               

7.参考

  1.《JAVA与模式》之抽象工厂模式

  2.设计模式:工厂方法模式(Factory Method)和抽象工厂模式(Abstact Factory)

原文地址:https://www.cnblogs.com/zhaoyanghoo/p/5452195.html