【问题标题】:Dynamically select which objects to create with an abstract factory pattern from xml使用 xml 中的抽象工厂模式动态选择要创建的对象
【发布时间】:2012-03-14 14:09:33
【问题描述】:

我希望这不是太具体。

我创建了一个 XML Schema,我用 XJC 编译它来获取类。 XML 基本上代表表单的一些元素(如文本字段、标签等)。 摘录如下:

<gruppoOggetti id="string" nome="string">
        <oggetto xsi:type="labelType" etichetta="string" id="string" obbligatorio="false" />
        <oggetto xsi:type="listaOpzioni" id="string" obbligatorio="1">
            <opzione id="string">string</opzione>
        </oggetto>
        <oggetto xsi:type="imageType" etichetta="string" id="string" obbligatorio="0" />
    </gruppoOggetti>

如您所见,对象的类型是从属性 xsi:type 定义的,所以当我使用 jaxb 解组 xml 时,它会自动建立正确的类。

现在的问题: 我正在实现一个抽象工厂来创建对象,所以基本上我必须根据 xml 说我必须创建的对象来调用我工厂的不同方法。 我现在使用的不太令人满意的方法是:

public OggettoBase creaOggetto(Factory f, OggettoType oggetto)
{
    String tipo = oggetto.getClass().getSimpleName().toString();
    OggettoBase ret = null;
    switch(tipo)
    {
        case "CheckBoxType": ret = f.createCheckbox(); break;
        case "ImageType":ret = f.createImage(); break;
        case "LabelType":ret = f.createLabel(); break;
        case "LinkType": ret = f.createLink(); break;
        case "ListaOpzioni": ret = f.createLista(); break;
        case "PasswordType": ret = f.createPassword(); break;
        case "RadiobuttonType": ret = f.createRadiobutton(); break;
        case "TextareaType": ret = f.createTextarea(); break;
        case "TextfieldType": ret = f.createTextfield(); break;
        default : System.out.println("Il tipo: "+tipo+" non esiste");
    }
    return ret;
}

我想使用其他方法(编辑:而不是 switch/case),我正在考虑枚举,但我并不完全在那里。我也不想使用反射。

【问题讨论】:

标签: java xml xsd abstract-factory


【解决方案1】:

嗯,对我来说,这并不是真正的工厂模式。工厂模式通常与Strategy Pattern 结合使用。所以我的建议是实现你的工厂,以便它只调用 f.CreateObject,它将返回一个可以调用更通用的 Create() 的对象。这样做的好处是它允许您的方法和类专注于它们特定的responsibility,并且任何时候您必须更改一项的功能,然后您不必重新构建其他项(如果您可以使用基类,如果你有共同的功能,也必须改变所有人)。如果您需要以下详细信息或推理,请告诉我。你甚至可以让 main 方法更像你的工厂,让代码更漂亮。

public OggettoBase creaOggetto(OggettoType oggetto)
{
    String tipo = oggetto.getClass().getSimpleName().toString();
    IObjectCreator creator = Factory.GetObjectCreator(tipo);
    if(creator == null)
        return null;
    return creator.Create();
}

public interface IObjectCreator
{
    OggettoBase Create(); 
}

public CheckboxCreator:IObjectCreator
{
    public OggettoBase Create()
    {
        return new Checkbox();
    }
}

//Repeat for each type

public static Factory
{
    public IObjectCreator GetObjectCreator(string tipo)
    {
        IObjectCreator creator;
        switch(tipo)
        {
            case "CheckBoxType": creator = new CheckboxCreator(); break;
            ...
            default : System.out.println("Il tipo: "+tipo+" non esiste");
        }
        return creator;
}

PS。我来自 C# 背景,所以如果某些语法不正确,请告诉我。但是,基本原则仍然适用

【讨论】:

  • 感谢您的回复!这很有趣,我可能也会实现它!但这并没有消除对我来说是原始问题的开关/外壳。抱歉,如果不清楚。
  • 不,它会将其卸载到负责解决此问题的类。 oodesign.com/factory-pattern.html 不过,我创建了一个使用哈希/字典的工厂。基本上,工厂构造函数在其构造函数中创建创建者类的实例,并将它们放入每种类型的字典中。然后,你只需要查字典。最终,逻辑是相同的。字典可能看起来更漂亮
  • 好的,我阅读了链接。该模式对于将动态产品添加到工厂很有趣,但最终它对我的应用程序来说有点矫枉过正。我需要抽象工厂,因为我会有不同的产品实现(例如 html 输出或 swing 或 GWT 网页)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多