抽象工厂模式——创建型模式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();
    }

}

XMLUtil.java

public class XMLUtil {

    public static Object getBeanFromXml(String beanName) {
        if (beanName == null || beanName.isEmpty()) {
            return null;
        }
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new File("config.xml"));
            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.xml

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

③ 测试

public class App {

    @Test
    public void test1() {
        Factory factory = (Factory) XMLUtil.getBeanFromXml("springFactory");
        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

 

posted @ 2015-11-09 20:03  学数学的程序猿  阅读(358)  评论(0编辑  收藏  举报