你的位置:首页 > ASP.net教程

[ASP.net教程]抽象工厂模式——创建型模式03


1. 定义


抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。抽象工厂模式又称为Kit 模式,它是一种对象创建型模式。

2. 问题


    现有这么一个需求:我们现在要为某软件定制2套皮肤,一套是Spring风格,一个是Summer风格,以后会继续扩展更多的皮肤。对于每种风格的皮肤,我们都需要设计出相应风格的Button、TextFiled等组件。结构示意图如下:

image

3. 解决方案


(1) 工厂方法模式

    如果采用上一篇中讲的工厂方法模式,我们首先需要抽象产品类和工厂类,即抽象出产品类Button和TextFiled类和工厂类ButtonFactory和TextFiledFactory类;然后根据具体的产品,我们需要实现SpringButton、SummerButton、SpringTextFiled、SummerTextFiled和它们对应的工厂SpringButtonFactory、SummerButtonFactory、SpringTextFiledFactory、SummerTextFiledFactory。如果我们需要再扩展其他的皮肤,只需要再给出相应的Button和TextField的实现,并给出相对应的工厂方法。

    根据上面的分析,此解决方案看似不错,它满足开闭原则,当增加新的皮肤时,我们不需要再修改现有代码,但实际上它是有缺陷的。一来当增加皮肤时,我们需要增加大量的工厂类;二来在我们的问题中,同一种风格的产品(工厂)是绑定在一起的,即SpringButton和SpringTextField是同时使用的,SummerButton和SummerTextField是同时使用的;而该方案并没有将同种风格的产品(工厂)绑定,这就有可能由于工厂的选择不当而造成界面风格的错乱。

(2) 抽象工厂模式

    由于工厂方法的这些缺陷,抽象工厂孕育而生。

介绍工厂方法之前,先介绍两个概率:

产品等级结构

    产品等级结构即产品的继承结构。例如问题中的抽象类Button,其子类有SpringButton,SummerButton,它们属于一个产品等级结构。

产品族

    在抽象工厂模式中,产品族是指由同一工厂生成的,位于不同产品等级结构的一组产品。如问题中的SpringButton、SpringTextField,它们属于一个产品族。

产品等级结构和产品族的示意图如下:

image

     采用抽象工厂方法,我们将一个产品族中的所有对象作为一个工厂的产品,即一个工厂负责一个产品族所有产品的生产,这样就可以大大减少工厂类(特别是在一个产品族中有多个产品的时候);而且在扩增产品族时,是满足开闭原则的(但是对于产品等级结构的扩充不满足,这种特性被称为开闭原则的倾向性)。

下面是用Java代码给出的具体解决方案:

① 抽象产品和工厂类

Button.java

public abstract class Button {  public Button() {    System.out.println("初始化Button...");  }  protected void setText(String text) {    System.out.println("设置Button内的文字...");  }}

TextField.java

public abstract class TextField {  public TextField() {    System.out.println("初始化TextFiled...");  }  protected void setText(String text) {    System.out.println("设置TextFiled内的文字...");  }}

Factory.java

public interface Factory {  public Button createButton();  public TextField createTextField();}

② 实现(这里只给出Spring风格的实现)

SpringButton.java

public class SpringButton extends Button {  public SpringButton() {    super();    System.out.println("初始化SpringButton...");  }}

SpringTextField.java

public class SpringTextField extends TextField{  public SpringTextField() {    super();    System.out.println("初始化SpringTextField...");  }}

SpringFactory.java

public class SpringFactory implements Factory {  @Override  public Button createButton() {    return new SpringButton();  }  @Override  public TextField createTextField() {    // TODO Auto-generated method stub    return new SpringTextField();  }}

public class public static Object getBeanFromif (beanName == null || beanName.isEmpty()) {      return null;    }    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();    try {      DocumentBuilder builder = factory.newDocumentBuilder();      Document document = builder.parse(new File("config.));      NodeList beansList = document.getElementsByTagName("beans");      if (beansList.getLength() == 0) {        return null;      }      NodeList beanList = beansList.item(0).getChildNodes();      for (int i = 0; i < beanList.getLength(); i++) {        if (beanList.item(i).getNodeType() == Node.ELEMENT_NODE) {          if (beanName.equals(beanList.item(i).getNodeName())) {            return Class.forName(beanList.item(i).getTextContent()).newInstance();          }        }      }    } catch (Exception e) {      e.printStackTrace();    }    return null;  }}

config.

<beans>  <springFactoryspringFactory>abstractMethod.factory.impl.SpringFactory</springFactory></beans>

③ 测试

public class App {  @Test  public void test1() {    Factory factory = (Factory) );    Button button = factory.createButton();    TextField textField = factory.createTextField();    System.out.println("Spring Style:" + button + textField);  }}

结果:

初始化Button...初始化SpringButton...初始化TextFiled...初始化SpringTextField...Spring Style:abstractMethod.product.impl.SpringButton@5b37e0d2abstractMethod.product.impl.SpringTextField@4459eb14