Ich möchte nicht die Vorzüge dieses Ansatzes diskutieren, nur wenn es möglich ist. Ich glaube, die Antwort ist "Nein". Aber vielleicht wird mich jemand überraschen!Ist es möglich in Java Affen zu patchen?
Stellen Sie sich vor, Sie haben eine Kern-Widget-Klasse. Es hat eine Methode calculateHeight()
, die eine Höhe zurückgibt. Die Höhe ist zu groß - dies führt zu Knöpfen, die zu groß sind. Sie können DefaultWidget erweitern, um ein eigenes NiceWidget zu erstellen und Ihre eigene calculateHeight()
zu implementieren, um eine bessere Größe zu erhalten.
Eine Bibliotheksklasse WindowDisplayFactory instanziiert DefaultWidget in einer ziemlich komplexen Methode. Sie möchten, dass Ihr NiceWidget verwendet wird. Die Methode der Fabrikklasse sieht in etwa so aus:
public IWidget createView(Component parent) {
DefaultWidget widget = new DefaultWidget(CONSTS.BLUE, CONSTS.SIZE_STUPIDLY);
// bunch of ifs ...
SomeOtherWidget bla = new SomeOtherWidget(widget);
SomeResultWidget result = new SomeResultWidget(parent);
SomeListener listener = new SomeListener(parent, widget, flags);
// more widget creation and voodoo here
return result;
}
Das ist der Deal. Das Ergebnis hat das DefaultWidget tief in einer Hierarchie anderer Objekte. Die Frage - Wie bekomme ich diese Factory-Methode, um mein eigenes NiceWidget zu verwenden? Oder zumindest meinen eigenen calculateHeight()
da drin. Im Idealfall würde Ich mag an Affen zu können DefaultWidget Patch, so dass seine calculateHeight das Richtige getan haben ...
public class MyWindowDisplayFactory {
public IWidget createView(Component parent) {
DefaultWidget.class.setMethod("calculateHeight", myCalculateHeight);
return super.createView(parent);
}
}
Was ist das, was ich in Python tun könnte, Ruby, etc. Ich erfunden habe die Name setMethod()
obwohl. Die anderen Optionen offen sind für mich:
- Kopieren und den Code der
createView()
Methode in meine eigene Klasse einfügen, die von der Factory-Klasse erbt mit Widgets - Leben, die zu groß sind
Die Die Factory-Klasse kann nicht geändert werden - sie ist Teil einer Core-Plattform-API. Ich habe versucht, über das zurückgegebene Ergebnis nachzudenken, um zu dem Widget zu kommen, das (irgendwann) hinzugefügt wurde, aber es sind mehrere Widget-Ebenen unten und irgendwo wird es verwendet, um andere Sachen zu initialisieren, was zu seltsamen Nebenwirkungen führt.
Irgendwelche Ideen? Meine Lösung ist bisher der Copy-Paste-Job, aber das ist ein Cop-Out, bei dem die Änderungen in der übergeordneten Factory-Klasse beim Upgrade auf neuere Versionen der Plattform protokolliert werden müssen, und ich wäre an weiteren Optionen interessiert.
Klingt gut und möglicherweise die nächste echte Lösung. Vielleicht ein bisschen Overkill, um eine Spring-Abhängigkeit hinzuzufügen, obwohl für die App nur für diese Korrektur keine existiert. Ein benutzerdefinierter Klassenlader funktioniert möglicherweise nicht gut mit Eclipse RCP, den ich auch verwende ... – richq
Sie brauchen Spring nicht, um AOP zu machen, nur AspectJ. Es gibt auch ein Eclipse-Plugin: http://www.eclipse.org/aspectj/ –