Las interfaces Java, el creador de los patrones y de la "getInstance()" método o equivalente

StackOverflow https://stackoverflow.com/questions/6811782

Pregunta

Me gustaría empezar por mencionar que mi problema se deriva del hecho de que las interfaces en Java no se permiten métodos estáticos.Ha habido debates acerca de la razón de esto en TAN (aquí , por ejemplo).Así que vamos a no pensar en eso.Estoy buscando una manera para mi de la interfaz para crear una instancia de sí mismo (o más bien, su aplicación), y el retorno que.A pesar de jugar con patrón Singleton, Factory y AbstractFactory patrones, todavía no puedo lograr mi objetivo.

Para ampliar la información sobre lo que estoy tratando de - aquí está mi interfaz:

public interface NoteDataStore {
    public boolean deleteNote(long noteId);
    public boolean addNote(Note note);
    public List<Note> listNotes();
    public boolean editNote(long noteId, Note note);
    public List<Note> search(String searchString);
}

Y aquí está mi capa de lógica de negocio:

public class BusinessLogicLayer {

    public BusinessLogicLayer(){
        /*
         * GOAL: To get an instance of NoteDataStore here,
         *  without being aware of the implementation class.
         */
    }

}

Traté de usar un patrón de fábrica así:

public interface NoteDataStoreFactory {
    public NoteDataStore getDataStoreInstance();
}

public class NoteDataStoreFactoryImpl implements NoteDataStoreFactory{
    public NoteDataStore getDataStoreInstance(){
        return NoteDataStoreImpl.getInstance();
        /*
         * Here, NoteDataStoreImpl is an implementation of NoteDataStore.
         * This should be transparent to my business logic layer.
         */
    }
}

Sin embargo, esto requiere que la capa de Lógica de Negocio para saber la clase de implementación NoteDataStoreFactoryImpl por lo tanto:

NoteDataStore = new NoteDataStoreFactoryImpl().getDataStoreInstance();

¿Cómo puedo evitar esto?¿Cómo puedo mantener mi BusinessLogicLayer en la oscuridad acerca de la exacta aplicación de la clase a usar?


EDITAR:Más en detalle los Antecedentes de mi problema

Algunas de las respuestas que sugieren el uso de frameworks como Spring.Por desgracia, no puedo hacerlo porque esta aplicación de diversos objetivos de las plataformas móviles (Android, Blackberry, JavaME).Yo debería haber hecho esto en claro en mi pregunta original - disculpas por no hacerlo.

Mi intención principal es tener una aplicación a través de plataformas.La interfaz de usuario, acceso a bases de datos, HTTP capas de transporte, etc tendrá que ser codificado específicamente para cada plataforma.Sin embargo, la lógica de negocio es lo suficientemente simple como para justificar una capa común a través de todas las plataformas.Tengo la intención de distribuir la capa de lógica de negocio como un FRASCO de la biblioteca.Así también, el análisis y el encuadre de la capa (para JSON/XML).

Ya ha habido una discusión acerca de esto en TAN (sobre si debo ser incluso yendo por este camino) - La lógica de la reutilización de Código.Sin embargo, suponiendo que esto está bien y que puedo continuar con el sistema de enfoque y la intención de tener una capa común en el código.Ahora, mi situación es que tengo:

  1. Un común Capa de Lógica de Negocio.
  2. Plataforma específica de la capa de datos (representado por el NoteDataStore interfaz)
  3. Específicos de la plataforma central de las Aplicaciones (capa de Controlador, si la puedo llamar así).

Tenga en cuenta que si puedo usar el patrón de Fábrica o de cualquier otro, me puedo permitir el lujo de tener esa capa específica para cada plataforma.Así, el método de fábrica/clase en sí misma puede saber acerca de la NoteDataStore implementación de la clase.Sin embargo, la Capa de Lógica de Negocio deben ser conscientes de cualquiera de las clases de implementación.

Un uso típico de las distintas capas sería como sigue:

public class NoteDataStoreAndroid implements NoteDataStore{

    public boolean deleteNote(long noteId){
        /*
         * Android-specific database code
         */
    }

    /* ... similarly, other methods */
}


public class AndroidCoreApp{

    public void doBusinessLogic(){
        BusinessLogicLayer businessLogic = new BusinessLogicLayer();
        businessLogic.startBusinessLogic();
    }
}

Entradas sobre cómo manejar esta situación?

¿Fue útil?

Solución 4

Finalmente fui por la sugerencia proporcionada por @Ray Tayek en un comentario a la pregunta original. Simplemente paso en una instancia del NoteDataStore En el momento de crear el BusinessLogicLayer.

Esta solución simple se adapta bastante bien a mis necesidades, ya que realmente no necesito una fábrica. Mi objetivo principal era que la capa BL no sea consciente de las clases de implementación exactas de las interfaces que utiliza. Ahora, en lugar de una fábrica, es la capa de "controlador" central que crea una implementación concreta de las interfaces y las suministra a la capa BL. ¡Esto es perfecto!

Aquí está el fragmento de código.

public class NoteDataStoreAndroid implements NoteDataStore{

    public boolean deleteNote(long noteId){
        /*
         * Android-specific database code
         */
    }

    /* ... similarly, other methods */
}


public class AndroidCoreApp{

    public void doBusinessLogic(){
        BusinessLogicLayer businessLogic = new BusinessLogicLayer(new NoteDataStoreAndroid());
        businessLogic.startBusinessLogic();
    }
}

public class BusinessLogicLayer {

    private NoteDataStore mDataStore;
    public BusinessLogicLayer(NoteDataStore dataStore){
        this.mDataStore = dataStore;

        //Do something useful with mDataStore
    }

    public void startBusinessLogic(){
        //Do something useful with mDataStore
    }

}

Otros consejos

Su clase debe aceptar una instancia de fábrica desde el exterior. Cuando crea una instancia usted mismo, no logras nada, tienes razón aquí.

Hay varias técnicas aquí. En general pertenecen a algo muy general llamado Inversión de control o COI para abreviar. También es útil saber sobre 'inversión de contenedores de control' o IOCC. Java tiene primavera, por ejemplo, lea aquí. Deberías preguntarle a los chicos de Java reales sobre los demás :)

También eche un vistazo a esto artículo.

Si desea devolver una implementación, puede hacerlo con un clase interior anónima

NoteDataStore myImplementation = new NoteDataStore (){
//Implement methods here
};

Has mirado en Coi/Inyección de Dependencia marcos como Guice y la Primavera?Se puede ser demasiado pesado para lo que usted está buscando, pero definitivamente solucionar el problema que se describe.Que permitan a todos de la capa de negocio de código escrito en contra de las interfaces, y las implementaciones reales a ser definidos a través de la Coi marco.Personalmente, soy un gran fan de la Primavera, y lo he usado en casi cada aplicación Java que he escrito en los últimos 6 años.

Sugiera que use marcos de identificación, como Guice y otros. No simplemente use el patrón de fábrica.

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