質問
私が参加した最近のプロジェクトのいくつかで、私は次のコーディングパターンにほとんど夢中になりました。 (これに適切な名前があるかどうかはわかりませんが、とにかく...)
何らかのオブジェクトが決定された状態にあり、私たちはこの状態を外部から変えようとしないとしましょう。これらの変更は、あらゆる動作を意味する可能性があり、あらゆるアルゴリズムを呼び出す可能性がありますが、事実は、彼らが状態の変化に焦点を合わせているということです (加盟国、データ状態など...) いくつかのオブジェクトの。
そして、それらのオブジェクトを変更する1つの個別の方法を呼び出しましょう Mutator
. Mutators
一度適用されます (一般的) そして、彼らはようないくつかの内部方法を持っています apply(Target& target, ...)
, 、これはすぐにオブジェクトの状態を変更することを引き起こします (実際、それらはある種の機能的なオブジェクトです)。
また、簡単に同化することもできます チェーン そして1つを適用しました(Mutator m1, m2, ...
);彼らはまた、いくつかの基本から派生することができます BasicMutator
と virtual void apply(...)
方法。
私は呼ばれるクラスを紹介しました InnerMutator
と ExplicitMutator
アクセスの点で異なります - 最初に変更することもできます 内部状態 オブジェクトの、そして友人として宣言されるべきです(friend InnerMutator::access;
).
これらのプロジェクトでは、私の論理は次のように機能するようになりました。
- 利用可能な突然変異体を準備し、適用するものを選択します
- 作成して設定します
object
いくつかの決定的な状態に foreach (mutator) mutator.apply(object);
今質問。
このスキームはうまく機能するようになります (私に) 標準以外ではあるが有用なデザインパターンのサンプルのようです。
私が不快に感じるのはそれです
InnerMutator
もの。 私は、状態を変更できるすべてのオブジェクトに友人を友人に宣言することは良い考えであり、適切な代替手段を見つけることはないと思います。この状況を解決することができますか
Mutators
それとも、同じ結果を伴ういくつかの代替パターンにアドバイスしていただけますか?
ありがとう。
解決
これが攻撃的に取られないことを願っていますが、このデザインはかなり単純な問題のための過度に派手なソリューションだと思わずにはいられません。
たとえば、なぜミューテーターを集約する必要があるのですか?単に書くことができます:
template <class T>
void mutate(T& t)
{
t.mutate1(...);
t.mutate2(...);
t.mutate3(...);
}
凝集した突然変異体のみがありますが、それは1つのスーパーミューテーターを作るミューテーターの組み合わせリストではなく、静的多型に依存する単純な関数テンプレートです。
私はかつてかなり似ていたかもしれない何かをしました。オペレーター&&によって両方のオペランドを適用したスーパー関数オブジェクトに組み合わせることができる関数オブジェクトを作成しました(左から右に順序で)、次のようなコードを書くことができます。
foreach(v.begin(), v.end(), attack && burn && drain);
それは本当にきちんとしていて、当時私には本当に賢いように見え、それはその場で新しい機能オブジェクトを生成したのでかなり効率的でした(ランタイムメカニズムは関係しません)が、私の同僚がそれを見たとき、彼らは私が非常識だと思った。振り返ってみると、私はすべてを詰め込み、その有用性を持つ機能的なスタイルプログラミングに詰め込もうとしていましたが、おそらくC ++では過度に依存するべきではありません。書くのは簡単だったでしょう:
BOOST_FOR_EACH(Something& something, v)
{
attack(something);
burn(something);
drain(something);
}
それはより多くのコードの行ですが、それは集中化され、デバッグしやすいという利点があり、私のコードを使用している他の人々にエイリアンの概念を紹介しません。代わりに、コードの行を強制的に削減しようとするのではなく、タイトなロジックに焦点を合わせるのがはるかに有益であることがわかりました。
これについて深く考え、このミューテーターベースのデザインを継続する価値があるかどうかを本当に考えることをお勧めします。他の人がすぐにそれを理解できない場合、あなたが著者をブーストする権限を持っていない限り、それを好きになるように人々を説得するのは難しいでしょう。
InnerMutatorについては、ペストのように避けるべきだと思います。ここでできる限り直接クラスの内部を変更できる外部変異クラスを使用すると、内部を持つという多くの目的を打ち負かします。
他のヒント
単にそれらを作る方が良いのではないでしょうか Mutator
彼らが変化しているクラスのs方法?共通の機能がある場合、いくつかのクラスに必要な機能が必要な場合は、同じ基本クラスから継承してみませんか?これを行うと、私が想像するすべての内部ミューテーターの不快感に対処します。
変更を行いたい場合は、クラス内のメソッドへの関数呼び出しセットとしてそれらを保存できます。