zoukankan      html  css  js  c++  java
  • 设计模式学习-抽象工厂模式

    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)

  • 相关阅读:
    自我理解:const char*, char const* and char *const
    获取任意控件的ID或窗口句柄
    Webmax 2.0开启无限量下载
    dotLucene搜索加入中文分词
    SQL SERVER获得指定表的主键
    LogExplore应用(ms sql server事物分析、数据恢复工具)[转载]
    电脑病之一
    查找数据库中记录数大于N的表
    视图
    获取生日提醒数据
  • 原文地址:https://www.cnblogs.com/zhaoyanghoo/p/5452195.html
Copyright © 2011-2022 走看看