zoukankan      html  css  js  c++  java
  • 抽象工厂模式——创建型模式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
  • 相关阅读:
    记一次渗透测试(5)
    记一次渗透实战(一)
    Spring IOC/DI
    Mysql 索引
    Mysql 存储过程
    Mysql 视图
    Mysql 用户和权限
    Mysql 事务
    Mysql 常用函数
    Mysql 子查询
  • 原文地址:https://www.cnblogs.com/dongkuo/p/4950923.html
Copyright © 2011-2022 走看看