Ist es wirklich unmöglich, einige Klassen in einer JAR-Datei zu verstecken?
Ich wollte die direkte Instanziierung der Klassen nicht zulassen, um sie flexibler zu halten. Nur die Fabrik (oder eine Fassade) sollte von diesem Glas sichtbar sein.
Gibt es einen anderen Weg, als dieses Problem zu lösen, als zwei Projekte zu erstellen? (Zwei Projekte: das erste enthält die Klassen (Implementierung) und das andere verweist auf das erste und enthält die Factory; später wird nur auf das zweite verwiesen)
Ich denke, Sie haben entweder einen Compilerfehler oder eine Warnung, wenn Ihre öffentliche Factory-Methode versucht, etwas zurückzugeben, was "versteckt" ist.
Nein, Sie können eine öffentliche Klasse nicht ausblenden, ohne Ihre eigene ClassLoader
erneut einzufügen oder OSGi oder ähnliches zu verwenden.
Was Sie tun können, ist, Schnittstellen-API von der Implementierung zu trennen, z. haben ein Projekt, das nur die Schnittstellen enthält und ein anderes Projekt, das die Implementierungen enthält. Sie können die Implementierungsklassen jedoch immer noch nicht ausblenden.
Ich verstehe, dass Sie nicht versuchen, die tatsächlichen Klassen zu verstecken, sondern nur ihre Konstruktion außerhalb einer Fabrikklasse verhindern. Dies kann, glaube ich, sehr leicht erreicht werden, indem die private Sichtbarkeit der Pakete in den Klassenkonstruktoren verwendet wird. Die einzige Einschränkung ist, dass Sie die Klassen und die Factory im gleichen Paket haben müssen, also in einer mittleren bis großen Codebasis können die Dinge unnötig komplex werden.
Wenn ich Ihre Frage richtig verstehe, möchten Sie sicherstellen, dass Benutzer Ihrer Bibliothek gezwungen sind, Ihre Factory zu verwenden, um ihre Objekte zu instanziieren, anstatt die Konstruktoren selbst zu verwenden.
Wie ich sehe, gibt es zwei Möglichkeiten, von denen eine doof ist, aber in wenigen, spezifischen Fällen brauchbar ist, und die andere ist die praktischste und wahrscheinlich am häufigsten verwendete Art, dies zu tun.protected
auf verwenden
Beschränken Sie den Zugriff auf Ihre Klasse
Konstruktoren. Das ist üblich
üben Sie , wenn Sie die -Fabrik verwenden
Muster . Mit Standard Classloadern ist eine einfache alte jar Dateien das ist nicht möglich. OSGi ist dieses Konzept, um nur einige Pakete und nicht andere Pakete sichtbar zu machen (d. H. Trennung von öffentlicher API und interner Implementierung).
Wenn Sie sich nicht entscheiden, können Sie solche Regeln mit diesem
erzwingenWenn ich Sie richtig verstehe, wenn Sie sagen, "um die direkte Instantiierung der Klassen nicht zuzulassen, um sie flexibler zu halten", wird ein korrekt ausgeführtes Fassadenmuster damit umgehen.
Beschränken Sie die Konstruktoren aller Klassen, die Sie ausblenden möchten, in den Paketbereich. Öffnen Sie die Fassadenklasse für den öffentlichen Bereich.
"Wenn Sie eine Variable oder Methode in haben Ihre Klasse, dass Sie keine Kunden wollen der Klasse, auf die direkt zugegriffen wird, gib es nicht öffentlich, geschützt oder private Erklärung. Aufgrund eines Aufsicht im Design von Java, Sie kann den Standard nicht explizit deklarieren "Paket" Zugänglichkeit. Andere Mitglieder des Pakets wird es sehen können, aber Klassen außerhalb des Pakets, das von dir erben, nicht. Das geschütztes Zugriffsattribut bietet etwas mehr sichtbar. EIN geschützte Methode ist sichtbar für Klassen erben, auch nicht Teil von das gleiche Paket. Ein Paketumfang (Standard) Methode ist nicht. Das ist das einziger Unterschied zwischen geschütztem und Paketumfang. "
Es gibt zwei Lösungen für Ihre Frage, bei denen nicht alle Klassen im selben Paket enthalten sind.
Die erste besteht darin, das Friend Accessor / Friend Package -Muster zu verwenden, das in (Practical API Design, Tulach 2008 ).
Die zweite Möglichkeit ist die Verwendung von OSGi. Es gibt einen Artikel hier , der erklärt, wie OSGi dies erreicht.
Du kannst solche Magie mit einem benutzerdefinierten Klassenlader machen, aber:
In solchen Situationen würde ich etwas tun, was dem im Standard-Java entspricht. Z. B. sehen Sie javax.xml.stream.XMLInputFactory
, aber irgendwo haben Sie com.sun.xml.internal.stream.XMLInputFactoryImpl
. Es ist perfekt kompilierbar, wenn Sie schreiben:
obwohl Sie es kaum tun werden :-) Mit einer Systemeigenschaft können Sie die tatsächliche Implementierung steuern, die geladen wird. Solcher Ansatz ist mir in vielen Situationen gut.
Ich hoffe ich habe deine Frage richtig verstanden;)
Prost!
Tags und Links java jar factory-pattern information-hiding facade