この説明に合うデザインパターンはありますか?無効化および有効化できるクラスを作成するファクトリ。クラスのユーザーは、機能が有効か無効かを知りません。クラスのメソッドを呼び出すだけです。この種のファクトリとクラスの適切な名前は何ですか?この擬似コードを正しく、スレッドセーフにするにはどうすればよいですか?
class FooFactory {
static enabled;
List foos = new ArrayList();
getFoo() {
Foo foo = new EnabledOrDisabledFoo(enabled);
foos.add(foo);
return foo;
}
setEnabled(boolean enabled) {
for (Foo foo : foos)
foo.setEnabled(enabled);
}
}
class EnabledOrDisabledFoo implements Foo {
private enabled;
private Foo;
EnabledOrDisabledFoo(boolean enabled) {
this.enabled = enabled;
}
setEnabled(boolean enabled) {
this.enabled = enabled;
}
doFoo() {
if (enabled)
foo.doFoo();
}
}
class FooConsumer {
Foo foo = FooFactory.getFoo();
foo.doFoo();
}
class FooManager {
FooFactory.setEnabled(true);
FooFactory.setEnabled(false);
FooFactory.setEnabled(true);
FooFactory.setEnabled(false);
}
あなたが説明することは、voidメソッドに対してのみ実行可能であり、何かを取得するには、いくつかのデフォルトを返す必要があります。
これを動的に行うには、委任を使用し、フラグに応じて受け渡しを有効/無効にします。
関連する手法があります:機能のルックアップ/ディスカバリー。
クラスFlyingAnimalの代わりに、Flyingの動的ルックアップを持つクラスAnimalを用意します。
機能/機能のテストを検討します。
interface Flying { void fly(); }
interface Swimming { void swim(); }
Animal animal = ...
Optional<Flying> flying = animal.lookup(Flying.class);
flying.ifPresent(f -> f.fly()); interface Flying { void fly(); }
Optional<Swimming> swimming = animal.lookup(Swimming.class);
swimming.ifPresent(sw -> sw.swim());
動物はインターフェースを実装する必要はありませんが、(lookup
または多分as
)機能を調べることができます。これは将来拡張可能で、動的です。実行時に変更される可能性があります。
としての実装
private Map<Class<?>, ?> map = new HashMap<>();
public <T> Optional<T> lookup(Class<T> type) {
Object instance = map.get(type);
if (instance == null) {
return Optional.empty();
}
return Optional.of(type.cast(instance));
}
<S> void register(Class<S> type, S instance) {
map.put(type, instance);
}
レジスタが(キー、値)エントリの安全な入力を保証するため、実装は安全な動的キャストを実行します。
lookupメカニズム(Optional
を使用)の利点は、その使用が最適に保護されることです。
パターンの命名について:元の概念はおそらく最も良い名前ですダミー/ヌルへの切り替えを伴う委任。
これの名前が特にあるかどうかはわかりません。 Strategy Pattern の簡略化された形式のように見えますが、これを Decorator Pattern または2つの組み合わせを使用するものとして説明することもできます。
このスレッドを安全にする最も簡単なことは、これを行うことです。
class EnabledOrDisabledFoo implements Foo {
private final AtomicBoolean enabled = new AtomicBoolean();
private Foo;
EnabledOrDisabledFoo(boolean enabled) {
setEnabled(enabled);
}
setEnabled(boolean enabled) {
this.set(enabled);
}
doFoo() {
if (enabled.get())
foo.doFoo();
}
}
これにより、setが呼び出されると、その後値を読み取るすべてのスレッドにその値が表示されるようになります。より複雑なスレッド調整要件がある場合は、これでは不十分な場合があります。