工厂方法模式

 在开发组件的时候比如button、text等,需要对这些组件做比较多的初始化工作,比如初始化长度等。传统的开发方案如下:

图 传统开发方案UML

上面的方案组件创建及组件的其他业务操作耦合在一起,违背了单一职责原则;在客户端Client需要知道具体的组件类名,才能创建对应的组件。

1 工厂方法模式概述

定义一个用于创建对象的接口,让子类决定将哪一个类实例化。针对不同的产品提供不同的工厂,系统提供一个与产品等级结构对应的工厂等级。

工厂方法模式_第1张图片

图 工厂方法模式UML

Product: 抽象产品类,是工厂模式所创建对象的超类型,也是产品对象的公共父类。

ConcreteProduct: 具体的产品类,由专门的具体工厂创建,具体工厂和具体产品之间一一对应。

Factory: 抽象工厂类,声名了创建产品的方法,是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。

ConcreteFactory: 具体的工厂类,实现了抽象工厂类中定义的工厂方法,可有客户端调用,返回一个具体产品类的实例。

1.1 工厂方法模式实现上述需求

public abstract class Module {

    private double width;

    private double height;

    private String name;

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name + "{" +
                "width=" + width +
                ", height=" + height +
                '}';
    }
}

public class ButtonModule extends Module{

}

public class TextModule extends Module{
}

/**
 * 在开发组件的时候比如button、text等,需要对这些组件做比较多的初始化工作,比如初始化长度等。
 */
public interface Factory {

    Module create();

}

public class ButtonFactory implements Factory{
    @Override
    public Module create() {
        ButtonModule module = new ButtonModule();
        module.setHeight(100.0);
        module.setName("button");
        // 其他初始化工作
        return module;
    }
}

public class TextFactory implements Factory{
    @Override
    public Module create() {
        TextModule textModule = new TextModule();
        textModule.setName("text");
        textModule.setHeight(123);
        //其他初始化操作
        return textModule;
    }
}

为了让系统具有更好的灵活性和可扩展性,客户端创建工厂对象时不再通过new关键字,而是通过存储在配置文件里的具体工厂类的类名,使用反射机制来创建具体的工厂。优化如下:



    com.huangmingfu.factory_method.ButtonFactory



public class FactoryMethodXmlUtil {

    public static Object getBean() {
        try {
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = dFactory.newDocumentBuilder();
            Document document = documentBuilder.parse(FactoryMethodXmlUtil.class.getClassLoader().getResourceAsStream("factory_method/concrete-factory.xml"));
            NodeList nodeList = document.getElementsByTagName("className");
            Node node = nodeList.item(0).getFirstChild();
            String className = node.getNodeValue();
            Class aClass = Class.forName(className);
            return aClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}

public class Client {

    public static void main(String[] args) {
        Factory factory;
        factory = (Factory) FactoryMethodXmlUtil.getBean();
        assert factory != null;
        System.out.println(factory.getClass());
        Module module = factory.create();
        System.out.println(module);
    }

}

2 优缺点

2.1 优点

1)向客户隐藏了产品类实例化细节,用户只需关心所需产品对应的工厂,无须关心创建细节,甚至无需知道具体产品类的类名;

2)扩展性好,符合开闭原则。

2.2 缺点

1)添加新的产品时,需要编写新的具体产品类及对应的具体工厂类,使得系统中类的个数成对增加,增加了系统复杂度及开销。

3 适用场景

  1. 客户不知道所需要的对象的类,只知道所对应的工厂。
  2. 对象创建时,需初始化操作多。

你可能感兴趣的:(设计模式的艺术,java,开发语言,设计模式)