3

私は現在、反復ソルバーを実装しています。これは、特定の問題に対するソリューションの推定値を連続的に改善することによって機能します。ソリューションはかなり大きなデータ セットであるため、その場で絞り込みが実行されます。

反復が行われている間にアルゴリズムを監視できるようにするために、単純な Observer/Observable パターンを実装しました。特に、ソルバーはメソッドを提供します。

Foo getCurrentSolution()

解の現在の推定値を返します。オブザーバーは、現在の推定値に基づいて自由に計算を行うことができます (たとえば、解が十分であるかどうか、反復を停止できるかどうかを判断するため)。Foo変更可能ですが、もちろん、オブザーバーが解の現在の推定値を変更すると、ソルバーの反復が台無しになる可能性があります。

したがって、getCurrentSolution()実際には防御コピーを返す必要があります。しかし、これは大規模な問題では時間とメモリを必要とするため、新しいをgetCurrentSolution()返すという別のアイデアを思いつきました。とほぼ同じインターフェースを持ち、データを変更する可能性のあるメソッドのみが「非アクティブ化」されます (例外がスローされます)。いくつかのダミー クラスのすべての詳細を以下に示します。ReadOnlyFoo(bar)fooReadOnlyFooFoo

私の質問は次のとおりです。このアプローチは良い習慣ですか?より良いパターンはありますか?

ありがとう!セバスチャン

public abstract class AbstractFoo{
    public abstract double getValue();

    public abstract void setValue(final double x);

    public abstract AbstractFoo add(AbstractFoo bar);

    public void addToSelf(AbstractFoo bar){
        setValue(getValue + bar.getValue());
    }
}

public class  Foo extends AbstractFoo{
    private double value;

    public Foo(final double x){
        value = x;
    }

    public double getValue(){
        return value;
    }

    public void setValue(final double x){
        value = x;
    }

    public AbstractFoo add(AbstractFoo bar){
        return new Foo(value + bar.getValue());
    }
}

public final class FooReadOnly extends AbstractFoo{
    private final Foo foo;

    public FooReadOnly(AbstractFoo foo){
        this.foo = foo;
    }

    public double getValue(){
        return foo.getValue();
    }

    public void setValue(final double x){
        throw new NotImplementedException("read only object");
    }

    public AbstractFoo add(AbstractFoo bar){
        return foo.add(bar);
    }

    public void addToSelf(AbstractFoo bar){
        throw new NotImplementedException("read only object");
    }
}
4

4 に答える 4

3

読み取り専用メソッドのみを含むインターフェイスと、すべてのメソッドを含むSolution変更可能なクラスを定義し、メソッドがインスタンスを返すようにします。このように、防御コピーを作成したり、ソリューションを読み取り専用ラッパーにラップしたりする必要はありません。MutableSolutiongetCurrentSolution()Solution

もちろん、オブザーバーは解を にキャストすることもできますMutableSolutionが、これは偶然ではありません。キャストから身を守りたい場合は、ラップされた を実装して委譲するReadOnlySolutionラッパー クラスを記述します。これは、メソッドの署名によってオブジェクトが可変ではないことが明確になることを除いて、あなたの命題に似ています。SolutionMutableSolution

于 2011-08-11T11:01:03.917 に答える
1

私はそれをしません。共通のインターフェース(実際の実装に存在する可能性があります)を使用するAbstractFoo場合でも、現在のインスタンスが変更可能かどうかは事前にわかりません。したがって、ユーザーは未チェックの例外がスローされる危険があります。

そして、不変オブジェクトの場合、変更不可能であることはまったく例外的ではありません。言い換えれば、 のインスタンスを変更しようとしたことを知らせるために execption を使用しませんFooReadOnly

少なくとも、オブジェクトを変更できるかどうかをテストできるようboolean isModifiable()に、抽象クラスに 抽象メソッドを追加します。AbstractFooその場合、例外をスローする必要はありません。変更メソッドの実装は、単純に何もできません。

于 2011-08-11T11:02:21.867 に答える
1

それは実際にCollectionsクラスが行うアプローチunmodifiableList(...)などです。元のリストを含むラッパーを返しますが、コレクションを変更するメソッドで例外をスローします。

于 2011-08-11T10:57:04.293 に答える
0

なぜこのような過剰設計されたソリューションを行うのでしょうか? 1 つのクラスと readOnly ブール属性を持たないのはなぜですか? 次に、各セッターに対して checkWriteable() を実行します。

于 2012-08-22T12:17:20.470 に答える