2009-07-30 19 views
6

Mejor explico la pregunta con un ejemplo. Tengo Interfaz Modelo que se puede utilizar para acceder a los datos. Puede haber diferentes implementaciones de Modelo que pueden representar los datos en varios formatos, por ejemplo, formato XMl, txt, etc. El modelo no se ocupa de los formatos. Digamos que una de esas implementaciones es myxmlModel.Force Singleton Pattern en una clase que implementa una interfaz

ahora quiero forzar myxmlModel y todos los demás implementación de Modelo seguir Singleton patrón .La forma habitual es hacer myxmlModels constructor privado y proporcionar un método de fábrica estática para devolver una instancia de myModel class.Pero el problema es interfaz no puede tener definiciones de métodos estáticos y un resultado no puedo aplicar una determinada definición de método de fábrica en todas las implementaciones de modelo. Por lo tanto, una implementación puede finalizar con getObject() y otra puede tener NewModel()..

Una solución es permitir el acceso al paquete de constructor de myxmlModel y crear una clase de fábrica que crea el myxmlModel objeto y almacenar en caché para su uso posterior.

Me preguntaba si hay una mejor manera de lograr la misma funcionalidad.

Respuesta

0

¿Se puede refactorizar la interfaz para que sea una clase abstracta? Esto le permitirá forzar un método de fábrica particular a todas las clases de implementación.

+0

Probé que la clase .Abstract no funcionará – Duleb

+1

El polimorfismo no funcionará en el caso de un método estático. Vea si tiene un método estático en la clase abstracta y lo reemplaza en la subclase; luego, si intenta acceder a ese método, se llamará al original, no al método de la subclase. – Duleb

+0

Ahhh, por supuesto, lo siento. – Steven

4
  1. Haga una fábrica que devuelva instancias de su interfaz, Modelo.
  2. Realice todas las implementaciones concretas del paquete de modelo-clases privadas en el mismo paquete que su fábrica.
  3. Si su modelo debe ser un singleton, y está usando java 5+, utilice enum en lugar del singleton tradicional, ya que es más seguro.
public enum MyXMLModel{ 
INSTANCE(); 
//rest of class 
}; 

EDIT: Otra posibilidad es crear clases de delegados que hacen todo el trabajo y luego utilizar una enumeración de proporcionar todas las Opciones de modelo.

por ejemplo:

class MyXMLModelDelegate implements Model { 
public void foo() { /*does foo*/} 
... 
} 

class MyJSONModelDelegate implements Model { 
public void foo() { /*does foo*/ } 
... 
} 

public enum Models { 
XML(new MyXMLModelDelgate()), 
JSON(new MyJSONModelDelegate()); 

private Model delegate; 
public Models(Model delegate) { this.delegate=delegate; } 

public void foo() { delegate.foo(); } 
} 
+0

La fábrica está bien. Pero tengo curiosidad por saber si se puede lograr la misma funcionalidad sin Factory. – Duleb

+0

Estoy trabajando en eclipse. La interfaz del modelo es el contrato para el punto de extensión. La implementación del modelo es la extensión. Entonces, debo exponer el myxmlModel. Si expongo alguna clase de Factory, dado que no implementa el modelo, el contrato fallará. – Duleb

0

le preguntaba la misma pregunta. Y propuse la misma respuesta ;-)

Ahora normalmente dejo caer el comportamiento de "forzar", confío en la documentación. No encontré ningún caso en el que el aspecto de Singleton fuera tan convincente que tuviera que aplicarse por todos los medios. Es solo una "mejor práctica" para el proyecto.

Normalmente utilizo Spring para instanciar un objeto de este tipo, y es la configuración de Spring la que lo convierte en Singleton. Seguro, y tan fácil ... más ventajas adicionales de Spring (como Proxying, sustituyendo un objeto diferente una vez para hacer algunas pruebas, etc.)

0

Esto es más una respuesta a tu comentario/aclaración a la respuesta de kts. ¿Es así, que el problema real no es utilizar el patrón de Singleton sino definir un esquema de punto de extensión de eclipse (equinoccio) que permita contribuir con un singleton?

Creo que esto no se puede hacer porque cada vez que llamas a IConfigurationElement.createExecutableExtension creas una nueva instancia. Esto es bastante incompatible con su requisito de singleton. Y, por lo tanto, necesita el constructor predeterminado público para que todos puedan crear instancias.

menos que se puede cambiar la definición del punto de extensión para que los plugins aportan una ModelFactory en lugar de un modelo, como

public interface ModelFactory { 

    public Model getModelInstance(); 

} 

De modo que el usuario de la extensión instancias de un ModelFactory y utilizarlo para obtener el producto único.

Si supuse mal, deje un comentario y elimino la respuesta;)

+0

Sí, tiene razón. Pero si expongo la Clase de fábrica, el Contrato (es decir, para implementar la interfaz del Modelo) fallará. Hay muchos otros métodos en IConfigurationElement que podemos usar para obtener más información acerca de la extensión, tal vez obtener el nombre de la clase y llamar a un método estático para obtener un Objeto. Pero nuevamente volvemos al punto uno. No podemos tener una declaración estática en la interfaz del Modelo. – Duleb

+0

No exactamente: el contrato se acaba de mover a la clase ModelFactory. Ahora tendrá dos contratos: la fábrica (contribución a través del punto de extensión) y el modelo (la fábrica debe devolver una implementación del modelo) –

2

Puede utilizar la reflexión. Algo como esto:

public interface Model { 
    class Singleton { 
    public static Model instance(Class<? extends Model> modelClass) { 
     try { 
     return (Model)modelClass.getField("instance").get(null); 
    } catch (blah-blah) { 
     blah-blah 
    } 
    } 
} 

public class XmlModel implements Model { 
    private static final Model instance = new XmlModel(); 

    private XmlModel() { 
    } 
} 

uso:

Model.Singleton.instance(XmlModel.class) 

En realidad, no me gusta mucho este código :). En primer lugar, utiliza la reflexión, muy lenta, en segundo lugar, existen posibilidades de errores de tiempo de ejecución en caso de definiciones erróneas de las clases.

+0

Creo que la reflexión funcionará. – Duleb

Cuestiones relacionadas