Pregunta

Estoy con el objetivo de crear un conjunto de objetos, cada uno de los cuales tiene un identificador único.Si ya existe un objeto con ese identificador, quiero usar el objeto existente.De lo contrario, quiero crear una nueva.Estoy tratando de no usar la palabra Singleton, porque sé que es una palabra sucia aquí...

Puedo usar un método de fábrica:

    // A map of existing nodes, for getInstance.
private static Map<String, MyClass> directory = new HashMap<String, MyClass>();

public static MyClass getInstance(String name) {
    MyClass node = directory.get(name);
    if(node == null) {
       node == new MyClass(name);
    }
    return node;
}

O igualmente, podría haber separado MyClassFactory método.

Pero yo tenía la intención de crear subclases de MyClass:

public class MySubClass extends MyClass;

Si yo no más, y la invocación de MySubClass.getInstance():

MyClass subclassObj = MySubClass.getInstance("new name");

...luego subclassObj será una llanura de Miclase, no MySubClass.

Sin embargo primordial getInstance() en cada subclase parece chapucero.

Hay una buena solución, me estoy perdiendo?


Esa es la versión generalizada de la pregunta.Más detalles, desde los ms responden preguntado por ellos.

El programa para la generación de un grafo dirigido de las dependencias entre los nodos que representan a las piezas de software.Subclases incluyen los programas de Java, Servicios Web, Almacenado de SQL procedimientos, message-driven disparadores, etc.

Para cada clase de "es-un" elemento en esta red, y tiene métodos para navegar y modificar las relaciones de dependencia con otros nodos.La diferencia entre las subclases de la implementación de la populate() el método utilizado para establecer el objeto de la fuente apropiada.

Digamos que el nodo denominado 'login.java' se entera de que tiene una dependencia en 'checkpasswd.sqlpl':

this.addDependency( NodeFactory.getInstance("checkpasswd.sqlpl"));

El problema es que la checkpasswd.sqlpl objeto puede o no puede ya existen en este momento.

¿Fue útil?

Solución

El método estático se define en la clase padre y también se llama estáticamente. Por lo tanto, no hay forma de saber en el método que lo ha llamado en la subclase. El compilador de Java probablemente incluso resuelva la llamada estáticamente a una llamada a la clase principal.

Por lo tanto, deberá volver a implementar el método estático en las clases secundarias que propone, o hacer que no sean estáticas para que pueda heredar (en una jerarquía de objetos de fábrica , no clases), o pasar un parámetro para indicar el tipo que desea crear.

Consulte el método EnumSet.noneOf (). Tiene un problema similar al que usted tiene, y lo resuelve pasando el método java.lang.Class. Puedes usar newInstance en la clase. Pero personalmente, solo usaría objetos de fábrica en lugar de clases con métodos estáticos.

Otros consejos

¿Has mirado en Guice? No estoy seguro de si resolvería su problema exactamente, pero actúa como una fábrica genérica y un contenedor de inyección de dependencia, y elimina las claves de cadena seguras que no son de tipo.

después de leer su explicación del problema, creo que lo está haciendo muy difícil para usted al subclasificar en la construcción de su gráfico. Creo que el problema se vuelve mucho más simple si separas el gráfico de dependencia de " información del programa "

use una interfaz como:

Public Interface Node<T> {
  public Object<T>    getObject();
  public String       getKey();
  public List<String> getDependencies();
  public void         addDependence(String dep);
}

y luego usa una fábrica para instanciar tus nodos

Parece implicar que en algún lugar sabes qué clase debería ser si no existe. Si implementa esa lógica en su fábrica, debería obtener las clases correctas.

De esta manera, tampoco deberías saber qué clase fue devuelta de fábrica.

También es probable que haga de 'MyClass' una interfaz si está considerando un patrón Factory.

La clase Class se parametriza con el tipo de instancia que puede crear. (por ejemplo: Class < String > es una fábrica para instancias de String).

No veo ninguna forma de conocer el tipo de instancia que se debe crear cuando obtiene OrCreate utilizando el método de fábrica aquí, por lo que recomendaría pasarlo al método y parametrizar el tipo que se genera:

private static Map<String, MyClass> directory = new HashMap<String, MyClass>();

public static <T extends MyClass> T getInstance(String name, Class<T> generatorClass)
{
  MyClass node = directory.get(name);    
  if(node == null) {
    node = generatorClass.getConstructor(String.class).newInstance(name);
    directory.put(name, node);
  }
  return node;
}

Además, noté que en realidad no estaba poniendo los nodos recién construidos en el directorio, supongo que es un descuido. También podría sobrecargar este método con otro que no haya tomado un generador y esté codificado al tipo predeterminado:

public static MyClass getInstance(String name) {
  return getInstance(name, MyClass.class);
}

Probablemente desee una inyección de dependencia. Generalizaría lo que está intentando hacer de alguna manera.

Además, la herencia probablemente tampoco sea exactamente lo que necesita. Nunca lo use a menos que pueda pasar & Quot; is-a & Quot; prueba. Si su clase heredada & Quot; Has-a & Quot; etiqueta de cadena única (esencialmente eso es lo que parece ser su clase) no significa que " is-a " ...

Sin embargo, puede hacer que uno sostenga al otro. Probablemente hay bastantes soluciones, pero A) no publicó toda su lista de requisitos para que podamos adivinar, y B) lo que probablemente quiera es la inyección de dependencia. :)

El patrón parece ser una especie de Optimización del rendimiento (estructuralmente, si no es un partido perfecto para el intento.)

El populate el método, como se ha descrito, podría ser asignado a la Template patrón, aunque no necesariamente responden a las preocupaciones expresadas.

Lo que yo sugiero es una generalización de la fábrica, con un create (en lugar de getInstance, lo que implica un Singleton, para mí de todos modos) método para los distintos tipos de esperar.

public static MyClass createJavaNode(String name, <differentiator>);
public static MyClass createSqlPlNode (String name, <differentiator>);
.
.
.

El conocimiento acerca de cómo un name se asigna a un <differentiator> es realmente una aplicación de su elección.Idealmente, habría una polimórficos create y la diferenciación sería por node tipo.El create método devuelve MyClass, pero es realmente devolución de las subclases.Me gustaría que consideren seriamente la posibilidad de hacer MyClass ya sea una interfaz o una clase abstracta, con un abstract populate método (hay la Template).

A partir de la descripción, lo que realmente parece que es la creación de un comportamiento que es diferente entre los tipos, no el comportamiento de la sub-clases de sí mismos, el caso para la refactorización de MyClass a una interfaz o clase abstracta se hace más fuerte.

Parafraseando a R.A.Heinlein, TANSTAAFL - No hay ninguna Tal Cosa Como Un Almuerzo Gratis -- en algún lugar el conocimiento de cómo crear los distintos tipos tiene que existir en la aplicación.Por lo que su elección es la de poner ese conocimiento en la clase de Fábrica, como algunas de las otras respuestas han expresado, o para separar la decisión de ¿ la aplicación se crea a partir de ¿ es creado.Parece que hay una capacidad de escanear un archivo de sistema y la recolección de la Nodes de ella.Que código (o puede) conocer la tipo de de la Node (la respuesta a la ¿) que debe ser creado.

Si que se implementa como un switch o en una más OO de la moda (en uno de los momentos donde el cuadro impulsado envío sería bueno) es hasta usted.Si esto es algo que podría ser útil, me puede ampliar aquí.

Por CIERTO, si el núcleo del comportamiento de MyClass necesita ser ampliado o modificado para algunas subclases, que es donde Decorator podría ser útil.


Original Respuesta:

Usted podría considerar la posibilidad de la Decorador o Plantilla Patrones De Diseño como alternativas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top