2012-03-25 12 views
0

Für ein Projekt, das wir eine Anforderung haben eine interfacedefinition zu erstellen, die alle verfügbaren Dateityp Erweiterungen zurückkehren, die unsere Komponente exportieren ...Java Struktur/Muster (n) bestimmtes Feld zurückzukehren, von Subklassen

Das Problem ist, dass Wir wollen Konfigurations-/Eigenschaftendateien vermeiden. Wir möchten unsere Konfigurations-/Eigenschaftendatei nicht bearbeiten, wenn in Zukunft ein anderer Dateityp hinzugefügt wird. Die Struktur dieses Teil unserer Komponente ist wie folgt:

public abstract class FileType { 
    protected String filetype; 

    public FileType(String filetype){ 
     this.filetype = filetype; 
    } 

    public abstract void export(String path, Object information); 
} 


public class PdfExport extends FileType { 
    public PdfExport() { 
     super("pdf"); 
    } 

    public void export(String path, Object information){ 
     //pdf specific logic 
    } 
} 

Aber wie wir dies lösen, wenn eine andere Komponente der interfacedefinition ruft getExportTypes()? (Wie erhalten wir eine Liste aller verfügbaren Dateitypen?) Unter Berücksichtigung der Anforderung, in Zukunft neue Klassen hinzuzufügen, die den abstrakten Klassendateityp erweitern (neue Dateitypen hinzufügen)?

Hat jemand Vorschläge hat, vielleicht eine andere Struktur des obigen Beispiels? Oder irgendwelche (Design), die oben genannten Thema diskutieren?

Vielen Dank im Voraus!

+2

würde ich vorschlagen, der ENUM zu nutzen. Dann werden Sie die Liste der verfügbaren Typen einfach durch Hinzufügen eines neuen Elements zur Enumeration. – khachik

+1

das Design ist klar, speichern Sie einfach alle Ihre Exporteure in Liste und geben Sie es zurück, wenn Sie getExportType() aufrufen. und ja, du musst deinen neuen Typ zu dieser Liste hinzufügen, wenn du einen neuen Expoter machst. –

Antwort

2

Dies ist der genaue Zweck der strategy pattern. Die Strategien hier sind die FileType s, die einen Algorithmus kapseln, der eine Datei exportiert. Im folgenden Beispiel:

public class Application{ 
List<FileType> exporters = new ArrayList<FileType>(); 
public void addExporter(FileType fileExporter){ 
    exporters.add(fileExporter); 
} 
public void exportData(Object information){ 
    for(FileType exporter : exporters){ 
    exporter.export("d:\Export", information); 
    } 
} 
} 

Die Application Klasse eine Liste der Ausführer hält, die auf dem Sprung gefüllt werden kann. Die Klasse Application muss nicht wissen, welcher Dateiexporttyp registriert ist und wie die Datei exportiert werden kann. Wenn die Daten exportiert werden, durchläuft die Klasse Applicaiton die registrierten Exporteure und delegiert die Exportaufgabe an jede von ihnen.

BEARBEITEN Im Folgenden finden Sie ein Beispiel für die Verwendung der Klasse Application.

// Define a pdf exporter 
PdfExport pdfExport = new pdfExport(); 
Application app = new Application(); 
// Register the new exporter 
app.addExporter(pdfExport); 
// Export some data... 
app.export(information); 

EDIT Wie Konfigurationsdateien und das Ändern des Code jedes Mal wenn Sie ein neues FileType haben zu vermeiden? Sie können die Exporteure zur Laufzeit mit Reflexion laden (siehe diese link für weitere Details)

+0

Welche Klasse ist verantwortlich für die Registrierung der Exporteure? – jtahlborn

+0

@jtahlborn In dem Beispiel, das ich in der Post gab, ist es die Klasse 'Application'.Dies kann durch jede Klasse ersetzt werden, die Sie wollen :) – GETah

+0

Ihr Beispiel hat keinen Code Aufruf von addExporter(). – jtahlborn

3

Sie so etwas tun könnte:

public interface FileType { 
    public String getFileType(); 
    public void export(String path, Object info); 
} 

public enum DefaultFileType implements FileType { 
    PDF(".pdf"){ 
     public void export(String path, Object info) { 
      // do pdf stuff 
     } 
    }, TXT(".txt"){ 
     public void export(String path, Object info) { 
      //do txt stuff 
     } 
    }; 

    private final String fileType; 

    private DefaultFileType(String fileType) { 
     this.fileType = fileType; 
    } 

    public String getFileType() { 
     return fileType; 
    } 

    public abstract void export(String path, Object info); 
} 

Dann können Sie die unterstützten FileType s Set<FileType> in der Klasse aller haben . Auf diese Weise kann jeder, der eine unterstützte FileType hinzufügen möchte, aber Ihre enum nicht bearbeiten kann, dies immer noch tun.

1

können Sie verwenden Reflexionsklassen zu scannen, die Ihre Schnittstelle implementieren.

Werfen Sie einen Blick auf ähnliche Frage: At runtime, find all classes in a Java application that extend a base class

+0

verknüpfen Sie eine gute Lösung. Der ServiceLoader-Mechanismus ist meistens nur eine gut definierte Konfigurationsdatei (weniger über Reflektion, mehr über die Konfigurationsdatei). Ich denke, es hängt vom OP ab, ob das der Definition "nicht bearbeiten einer Konfigurationsdatei" entspricht oder nicht. – jtahlborn

Verwandte Themen