Java -Schnittstellen, die Schöpfermuster und die Methode „getInstance ()“ oder die Äquivalent

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

Frage

Ich möchte zunächst erwähnen, dass mein Problem darauf zurückzuführen ist, dass Schnittstellen in Java keine statischen Methoden zulassen. Es gab Diskussionen über den Grund dafür (hier , zum Beispiel). Lassen Sie uns also nicht darüber nachdenken. Ich suche nach einer Möglichkeit für meine Schnittstelle, eine Instanz von sich selbst (vielmehr seine Implementierung) zu erstellen und dies zurückzugeben. Obwohl ich mit dem Singleton -Muster, den Fabrik- und AbstractFactory -Mustern herumspielen kann, kann ich mein Ziel immer noch nicht erreichen.

Um das zu nähern, was ich versuche - hier ist meine Benutzeroberfläche:

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);
}

Und hier ist meine Geschäftslogikschicht:

public class BusinessLogicLayer {

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

}

Ich habe versucht, ein Werksmuster wie SO zu verwenden:

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.
         */
    }
}

Dies erfordert jedoch weiterhin die Geschäftslogikschicht, um die Implementierungsklasse zu kennen NoteDataStoreFactoryImpl daher:

NoteDataStore = new NoteDataStoreFactoryImpl().getDataStoreInstance();

Wie komme ich damit um? Wie halte ich meinen Businesslogiclayer in Bezug auf die genaue Implementierungsklasse im Dunkeln?


Bearbeiten: detaillierterer Hintergrund meines Problems

Einige der Antworten deuten auf die Verwendung von Frameworks wie Frühling hin. Leider kann ich dies nicht tun, da diese Anwendung verschiedene mobile Plattformen (Android, Blackberry, Javame) abzielt. Ich hätte das in meiner ursprünglichen Frage deutlich machen sollen - Entschuldigung dafür, dass er dies nicht getan hat.

Meine Hauptabsicht ist es, eine App über Plattformen hinweg zu haben. Die Benutzeroberfläche, die Datenbankzugriff, die HTTP -Transportebenen usw. müssen für jede Plattform speziell codiert werden. Die Geschäftslogik ist jedoch einfach genug, um eine gemeinsame Ebene auf allen Plattformen zu rechtfertigen. Ich beabsichtige, die Geschäftslogikschicht als JAR -Bibliothek zu verteilen. So auch die Parsing- und Rahmenschicht (für JSON/XML).

Es gab bereits eine Diskussion darüber bei SO (darüber, ob ich überhaupt diesen Weg gehen sollte) - Wiederverwendung von Logikcode. Angenommen, dies ist in Ordnung und ich gehe mit dem Schichtansatz und der Absicht fort, eine Schicht im Code zu haben. Jetzt ist meine Situation so, dass ich:

  1. Eine gemeinsame Geschäftslogikschicht.
  2. Plattformspezifische Datenschicht (dargestellt durch die NoteDataStore Schnittstelle)
  3. Plattformspezifische Anwendungskernschicht (Controller, falls ich sie so nennen darf).

Beachten Sie, dass ich es mir leisten kann, diese Ebene für jede Plattform spezifisch zu haben, wenn ich das oder andere Fabrikmuster verwende. Die Fabrikmethode/Klasse selbst kann also über die wissen NoteDataStore Implementierungsklasse. Die Geschäftslogikschicht muss sich jedoch einer der Implementierungsklassen nicht bewusst sein.

Eine typische Verwendung der verschiedenen Schichten wäre wie folgt:

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();
    }
}

Irgendwelche Eingaben, wie man mit diesem Szenario umgeht?

War es hilfreich?

Lösung 4

Ich habe schließlich den Vorschlag von @ray Tayek in einem Kommentar zur ursprünglichen Frage entschieden. Ich gehe einfach in einer Instanz der NoteDataStore Zum Zeitpunkt des Erstellens der BusinessLogicLayer.

Diese einfache Lösung passt zu meinen Bedürfnissen ziemlich gut, da ich keine Fabrik benötige. Mein Hauptziel war es, dass die BL -Schicht die genauen Implementierungsklassen der von ihr verwendeten Schnittstellen nicht bewusst war. Anstelle einer Fabrik ist es nun die Kernschicht "Controller", die eine konkrete Implementierung der Schnittstellen erzeugt und sie der BL -Schicht liefert. Das ist einfach perfekt!

Hier ist der Code -Snippet.

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
    }

}

Andere Tipps

Ihre Klasse sollte die Fabrikinstanz von außen annehmen. Wenn Sie selbst eine Instanz erstellen - Sie erreichen nichts, Sie haben hier Recht.

Hier gibt es mehrere Techniken. Im Allgemeinen gehören sie zu etwas sehr Allgemeinem, das genannt wird Kontrollinversion oder kurz IOC. Es ist auch nützlich, über "Inversion von Kontrollbehälter" oder IOCC zu wissen. Java hat zum Beispiel Frühling - lesen hier. Du solltest echte Java -Jungs nach anderen fragen :)

Schauen Sie sich das auch an Artikel.

Wenn Sie eine Implementierung zurückgeben möchten, können Sie dies mit einem tun Anonyme innere Klasse

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

Haben Sie sich IOC/Abhängigkeitsinjektionsrahmen wie Guice und Frühling angesehen? Sie sind vielleicht zu schwer, für das, wonach Sie suchen, aber sie lösen definitiv das Problem, das Sie beschreiben. Sie ermöglichen es, dass Ihr Geschäftsschichtcode an Schnittstellen und den tatsächlichen Implementierungen über das IOC -Framework definiert wird. Ich persönlich bin ein großer Fan von Frühling und habe es in fast jeder Java -App verwendet, die ich in den letzten 6 Jahren geschrieben habe.

Schlagen Sie vor, Sie verwenden ID -Frameworks wie Guice und andere. Verwenden Sie nicht einfach das Fabrikmuster.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top