22

可能であれば、このアプローチのメリットについては議論したくありません。答えは「いいえ」だと思います。しかし、誰かが私を驚かせるかもしれません!

コア ウィジェット クラスがあるとします。calculateHeight()高さを返すメソッドがあります。高さが大きすぎます - これにより、(たとえば) ボタンが大きすぎます。DefaultWidget を拡張して独自の NiceWidget を作成し、独自のものを実装してより適切calculateHeight()なサイズを返すことができます。

現在、ライブラリ クラス WindowDisplayFactory は、かなり複雑なメソッドで DefaultWidget をインスタンス化しています。あなたは、NiceWidget を使用したいと考えています。ファクトリ クラスのメソッドは次のようになります。

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

それが取引です。その結果、DefaultWidget は他のオブジェクトの階層の奥深くにあります。質問 - このファクトリ メソッドを取得して自分の NiceWidget を使用するにはどうすればよいですか? または、少なくとも自分のものcalculateHeight()をそこに入れます。理想的には、DefaultWidget にモンキー パッチを適用して、その calculateHeight が正しいことを実行できるようにしたいと考えています...

public class MyWindowDisplayFactory {
    public IWidget createView(Component parent) {
        DefaultWidget.class.setMethod("calculateHeight", myCalculateHeight);
        return super.createView(parent);
    }
}

これは私が Python や Ruby などでできることです。名前は私が思いつきましたsetMethod()。私に開かれている他のオプションは次のとおりです。

  • createView()ファクトリ クラスから継承する独自のクラスにメソッドのコードをコピー アンド ペーストする
  • 大きすぎるウィジェットとの生活

ファクトリ クラスは変更できません。コア プラットフォーム API の一部です。返された結果を反映して、(最終的に) 追加されたウィジェットにたどり着きましたが、それはいくつかのウィジェット層であり、どこかで他のものを初期化するために使用され、奇妙な副作用を引き起こしています。

何か案は?これまでの私の解決策はコピー アンド ペーストの仕事ですが、それはプラットフォームの新しいバージョンにアップグレードするときに親ファクトリ クラスの変更を追跡する必要があるため、他のオプションを聞くことに興味があります。

4

9 に答える 9

9

おそらく、アスペクト指向プログラミングを使用して、その関数への呼び出しをトラップし、代わりに独自のバージョンを返すことができますか?

SpringはいくつかのAOP機能を提供しますが、それを実行する他のライブラリもあります。

于 2008-12-19T15:26:09.267 に答える
7

醜い解決策の 1 つは、(同じ FQCN を持つ) DefaultWidget の独自の実装を、通常の実装よりも前にクラスパスに配置することです。これはひどいハックですが、私が考えることができる他のすべてのアプローチはさらに悪いものです。

于 2008-12-19T15:14:46.030 に答える
3

あくまでも私のコンセプト案ですが、

AOP をバイトコード エンジニアリングの方法で使用して、calculateHeight メソッドにアスペクトを挿入することが可能です。

次に、ThreadLocal または else 変数によるパッチを有効にすることができます。

于 2008-12-19T15:28:12.647 に答える
2

cglibは、モンキー パッチに似たいくつかのことを実行できる Java ライブラリです。実行時にバイトコードを操作して、特定の動作を変更できます。必要なことを正確に実行できるかどうかはわかりませんが、一見の価値があります...

于 2008-12-19T17:00:04.710 に答える
0

これを行うオブジェクト指向の方法は、IWidgetを実装するラッパーを作成し、calculateHeightを除くすべての呼び出しを実際のウィジェットに委任することです。

class MyWidget implements IWidget {
    private IWidget delegate;
    public MyWidget(IWidget d) {
        this.delegate = d;
    }
    public int calculateHeight() {
        // my implementation of calculate height
    }
    // for all other methods: {
    public Object foo(Object bar) {
        return delegate.foo(bar);
    }
}

これを機能させるには、置き換えるウィジェットのすべての作成をインターセプトする必要があります。これは、WidgetFactoryの同様のラッパーを作成することを意味します。また、使用するWidgetFactoryを構成できる必要があります。

また、IWidgetをDefaultWidgetにキャストしようとしているクライアントがいないかどうかにも依存します...

于 2008-12-19T15:21:18.510 に答える
0

私が考えることができる唯一の提案:

  1. ライブラリAPIを調べて、デフォルトを上書きしてサイズを変更する方法があるかどうかを確認します。サイズ設定は、(少なくとも私にとっては)swing、setMinimum、setMaximum、setdefault、setDefaultOnThursday、...で混乱する可能性があります。方法がある可能性があります。ライブラリの設計者に連絡できれば、不快なハッキングの必要性を軽減する答えが見つかるかもしれません。

  2. おそらく、デフォルトのサイジングパラメータをオーバーライドするだけでファクトリを拡張しますか?工場によって異なりますが、可能かもしれません。

同じ名前のクラスを作成することが他の唯一のオプションかもしれません。他の人がそれは醜いと指摘しているので、APIライブラリを更新したり、別の環境にデプロイしたりして、なぜ持っていたのかを忘れると、それを忘れて壊れてしまう傾向があります。クラスパスはそのように設定されます。

于 2008-12-19T15:22:27.247 に答える
-1

ええと、私は提案を投稿しようとし続けます、そしてそれから私はそれらがうまくいかないか、あなたがそれらを試したとあなたがすでに述べたのを見ます。

私が考えることができる最善の解決策は、WindowDisplayFactoryをサブクラス化し、次にサブクラスのcreateView()メソッドで、最初にsuper.createView()を呼び出し、次に返されたオブジェクトを変更してウィジェットを完全に破棄し、それをサブクラスのインスタンスに置き換えることです。あなたが望むことをします。ただし、ウィジェットはものを初期化するために使用されるため、それらすべてを変更する必要があります。

次に、createView()から返されたオブジェクトにリフレクションを使用して、その方法で問題を修正しようと考えますが、ウィジェットで初期化されたものが非常に多いため、これも厄介です。ただし、コピーと貼り付けよりも正当化できるほど単純な場合は、そのアプローチを使用しようと思います。

私はこれを見て、さらに他のアイデアを思い付くことができるかどうかを考えています。Java Reflectionは確かに素晴らしいですが、PerlやPythonなどの言語で利用できる動的な内省に勝るものはありません。

于 2008-12-19T15:43:47.763 に答える