具有单例模式和静态方法的多个子子句&变量

时间:2014-01-23 22:45:58

标签: java design-patterns static abstract-class subclass

很抱歉我的英语,我可以尽我所能解释这个问题。

问题

我有多个类,它从唯一的XML文件中读取更多字符串。

所有这些clases都从同一个文件中读取,但变量是不同的。因为每个类都读取文档的不同部分。

这个变量我想用“静态”。因为每次我使用该类时我都不想实例化。

我使用这些类来返回“动态”URL。我在Forms,Links,JSP和“request.getRequestDispatcher(#)”中使用这些URL。

这就是为什么使用“静态”方式不在JSP / Servlet中实例化类并且可以直接使用它。 (代码更简单,更干净)

班级示例:

public class PaginasProductos {

Logger log = LoggerFactory.getLogger(getClass());

// URL donde se encuentran las paginas
private static String PATH;
// URL para las acciones
private static String RealPath = PaginasGlobales.getPATH();

//Paginas
private static String PaginaListados;
private static String FormularioModificar;
private static String FormularioAlta;


// Acciones = Servlets
private static String AccionAlta;
private static String AccionBaja;
private static String AccionListar;
private static String AccionModificar;
private static String AccionObtener;

// Instancia de la clase
private static PaginasProductos INSTANCIA;

/**
 * Devuelve las URL de las paginas especificas de administracion de productos
 * @return Una instancia con todas las URL de las paginas
 */

public static PaginasProductos getInstance(){
    if (INSTANCIA == null) INSTANCIA = new PaginasProductos();
    return INSTANCIA;
}//Final del metodo, getInstance

private PaginasProductos(){
    String rutaTotal = InicializadorXML.getRutaXmlPaginas();
    SAXBuilder constructor = new SAXBuilder();
    File xml = new File(rutaTotal);
    try{
        Document documento = (Document) constructor.build(xml);

        Element root = documento.getRootElement();

        List<Element> listado = root.getChildren("paginasProductos");

        for (int contador = 0; contador < listado.size(); contador++){
            Element parametro = (Element) listado.get(contador);

            PATH = parametro.getChildText("path");

            PaginaListados = PATH+parametro.getChildText("listado");

            FormularioModificar = PATH+parametro.getChildText("formularioMod");

            FormularioAlta = RealPath+PATH+parametro.getChildText("formularioAlta");

            AccionAlta = RealPath+parametro.getChildText("alta");

            AccionBaja = RealPath+parametro.getChildText("baja");;

            AccionListar = RealPath+parametro.getChildText("listar");

            AccionModificar = RealPath+parametro.getChildText("modificar");

            AccionObtener = RealPath+parametro.getChildText("obtener");
            }
        }catch (IOException e) {
            log.error("Ex (IOException | Constructor | PaginaProductos): " + e.getMessage());
            log.error("¡traza!", e);
        }catch (JDOMException e) {
            log.error("Ex (IOException | Constructor | PaginaProductos): " + e.getMessage());
            log.error("¡traza!", e);
        }catch (Exception e) {
            log.error("Ex (Exception | Constructor | PaginaProductos): " + e.getMessage());
            log.error("¡traza!", e);
        }   
} //Fin Constructor PaginasClientes

@SuppressWarnings("javadoc")
public static String getPaginaListados() {
    return PaginaListados;
}

@SuppressWarnings("javadoc")
public static String getFormularioModificar() {
    return FormularioModificar;
}

@SuppressWarnings("javadoc")
public static String getFormularioAlta() {
    return FormularioAlta;
}


@SuppressWarnings("javadoc")
public static String getAccionAlta() {
    return AccionAlta;
}


@SuppressWarnings("javadoc")
public static String getAccionBaja() {
    return AccionBaja;
}


@SuppressWarnings("javadoc")
public static String getAccionListar() {
    return AccionListar;
}


@SuppressWarnings("javadoc")
public static String getAccionModificar() {
    return AccionModificar;
}


@SuppressWarnings("javadoc")
public static String getAccionObtener() {
    return AccionObtener;
}} //Fin Clase PaginasClientes

现在我所做的是相同的代码,替换“paginasProductos”,为每个类读取他们的XML部分。

但我认为存在另一种方法。因为我认为我可以重用代码而不是每个类再次写入

我尝试过的事情

生成包含此代码的Abstract类。其他条款“扩展”了这一点。

故障

由于“父”类具有静态方法,因此不会替换它们。变量总是具有相同的值。

可行解决方案 我读到了“工厂模式”,但是如果它解决了我的问题,那就基本上重新编写每个类的代码,如果我做出更改就更容易维护

我试着想办法,但我想不出比以前测试过的更好的东西

修改

这是XML文件:

http://pastebin.com/aXS0aCxP

  • 我使用大写字母变量名称因为是“静态”而且我用它将它与其他变量分开。通常我使用java命名法
  • XML文件包含webapp URL和有关Webapp的其他信息(domain,port..etc)。只有此信息会更改( paginasGlobales

如果有人需要进一步解释或更好地解释(我的英语不好),我会尝试再次更清楚地解释

2 个答案:

答案 0 :(得分:1)

由于您目前的方法是由一系列反模式构成的,因此我将从一些一般性考虑开始。这不是解决您的问题,但可能会指导您的方式。缺少一些基本信息,但根据代码,我将做出以下假设:

  • 您正在开发WebApplication(* .war)
  • 您希望将存储在XML文件中的信息缓存一段未知的时间。
  • 您希望分离代码以加载xml的特定部分

以下是我的建议:

  • 应该避免在WebApp中使用静态声明,至少如果您不想应对所有“线程安全”注意事项。如果您想要查看WebApplication的范围的单个实例,尤其是您的案例中的 ApplicationScope 。这样你就可以摆脱静态问题。

  • 如何构建代码以仅加载XML文件一次并应用不同的“Reader-Logic” CommandPattern 将告诉您。你提到了子类化,这将是它的一部分。

  • 读取XML文件的代码的和平不需要是静态的。只需检查数据是否已加载,就像您在已应用的单例模式中检查实例一样。

  • 在Java中,请不要使用大写变量名。始终以小写字母开头。

为了获得更具体的答案,有些人需要了解XML-Content的生命周期。它是静态的还是在服务器运行时会改变?在后一种情况下,您可以应用基于时间的缓存实现。其中有很多都是为了Java。

再见,理解你的英语绝对没问题,希望同样适用于我的; - )

答案 1 :(得分:1)

我会使用HashMap来存储产品。如果您需要添加新产品,只需向productos添加新值即可。你可以发布你的XML文件吗?

public class PaginasProductos {
     private HashMap<String,String> paginasProductos;
     private String[] productos = {"listado", "formularioMod", ...};

     .....

     public PaginasProductos(){
         String rutaTotal = InicializadorXML.getRutaXmlPaginas();
         SAXBuilder constructor = new SAXBuilder();
         File xml = new File(rutaTotal);
         try{
             Document documento = (Document) constructor.build(xml);
             Element root = documento.getRootElement();
             List<Element> listado = root.getChildren("paginasProductos");
             PATH = parametro.getChildText("path");

             for (int contador = 0; contador < listado.size(); contador++){
                 Element parametro = (Element) listado.get(contador);

                 for(String producto:productos){
                     paginasProductos.put(producto, PATH+parametro.getChildText(producto));
                 }
             }
         }
     }

     public String getProducto(String producto){
         return paginasProductos.get(producto)
     }

}

修改

根据您提供的XML(下面的代码段),您的代码可以简化。

  <paginasProductos>
    <path>administracion/productos/</path>
    <listado>gestionProductos.jsp</listado>
    <formularioMod>formularioModificarProducto.jsp</formularioMod>
    <formularioAlta>formularioAltaProducto.jsp</formularioAlta>
    <alta>AltaProducto</alta>
    <baja>BajaProducto</baja>
    <listar>ListarProductos</listar>
    <modificar>ModificarProducto</modificar>
    <obtener>ObtenerProducto</obtener>
  </paginasProductos>

重构代码无需了解productos。只需在<paginasProductos>代码中添加另一个子元素,即可生成新的producto

public class PaginasProductos {
     private HashMap<String,String> paginasProductos;

     .....

     public PaginasProductos(){
         String rutaTotal = InicializadorXML.getRutaXmlPaginas();
         SAXBuilder constructor = new SAXBuilder();
         File xml = new File(rutaTotal);
         try{
             Document documento = (Document) constructor.build(xml);
             Element root = documento.getRootElement();
             List<Element> listado = root.getChildren("paginasProductos");
             PATH = parametro.getChildText("path");

             for (int contador = 0; contador < listado.size(); contador++){
                 Element parametro = (Element) listado.get(contador);
                 paginasProductos.put(parametro.getTagName(), PATH+parametro.getChildText(producto));
             }
         }
     }

     public String getProducto(String producto){
         return paginasProductos.get(producto)
     }

}

修改

根据您的评论,您可以进一步重构:

public class Paginas {
     private HashMap<String,String> paginas;

     .....

     // sectionName = "paginasProductos", etc.
     public Paginas(String sectionName ){
         String rutaTotal = InicializadorXML.getRutaXmlPaginas();
         SAXBuilder constructor = new SAXBuilder();
         File xml = new File(rutaTotal);
         try{
             Document documento = (Document) constructor.build(xml);
             Element root = documento.getRootElement();
             List<Element> listado = root.getChildren(sectionName );
             PATH = parametro.getChildText("path");

             for (int contador = 0; contador < listado.size(); contador++){
                 Element parametro = (Element) listado.get(contador);
                 paginas.put(parametro.getTagName(), PATH+parametro.getChildText(producto));
             }
         }
     }

     public String getPaginas(String page){
         return paginas.get(page);
     }

}

现在,您为XML文件中的每个组创建一个Paginas实例。也许你可以有一个PaginasManager来保持它们在一起。

public class PaginasManager{
    private HashMap<String,String> paginasSections;

    ....

    public PaginasManager(String[] sectionNames){
        for(String sectionName:sectionNames){
            paginasSections.put(sectionName, new Paginas(sectionName));
        }
    }

    public String getPaginas(String section, String page){
        return paginasSections.get(section).get(page);
    }
}