多くの人が同意しているようです。シングルトンパターンには多くの欠点があり、パターンを完全に回避することを提案する人もいます。ここで素晴らしい議論があります。シングルトンパターンに関するコメントは、その質問に向けてください。
私の質問:他のデザインパターンはありますか?
多くの人が同意しているようです。シングルトンパターンには多くの欠点があり、パターンを完全に回避することを提案する人もいます。ここで素晴らしい議論があります。シングルトンパターンに関するコメントは、その質問に向けてください。
私の質問:他のデザインパターンはありますか?
回答:
すべての設計パターンは注意して使用する必要があります。私の意見では、パターンをすぐに実装するのではなく、正当な理由がある場合はパターンにリファクタリングする必要があります。パターンの使用に関する一般的な問題は、パターンが複雑になることです。パターンを使いすぎると、特定のアプリケーションやシステムをさらに開発して維持するのが面倒になります。
ほとんどの場合、簡単な解決策があり、特定のパターンを適用する必要はありません。大まかな目安としては、コードの一部が頻繁に置き換えられる、または頻繁に変更される必要がある場合は常にパターンを使用し、パターンを使用するときに複雑なコードの警告に対応できるようにしてください。
コードの変更をサポートするための実用的なニーズがある場合は、単純な目標を設定し、パターンを採用することを忘れないでください。
パターンが明らかに過度に設計された複雑なソリューションにつながる可能性がある場合、パターンを使用することは意味がないように思えるかもしれません。ただし、プログラマにとっては、ほとんどのパターンの基礎となる設計手法と原則について読む方がはるかに興味深いです。実際、「デザインパターン」に関する私の好きな本の 1つは、問題のパターンに適用できる原則を繰り返し説明することで、これを強調しています。それらは、関連性の点でパターンよりも有用であるほど十分に単純です。コードのモジュールを作成できる限り、いくつかの原則は、Liskov Substitution Principleなどのオブジェクト指向プログラミング(OOP)以上を網羅するのに十分一般的です。
多数の設計原則がありますが、GoFブックの最初の章で説明されているものは、最初から非常に役立ちます。
それらをしばらくの間あなたに沈めてみましょう。GoFが作成されたとき、インターフェイスは抽象化(スーパークラスも意味する)を意味し、JavaまたはC#の型としてのインターフェイスと混同しないように注意してください。第二の原則は、今日でも悲しいことに一般的である、継承の過剰使用の観察から来ています。
そこから、ロバートセシルマーティン(別名、ボクルおじさん)によって知られるようになったSOLIDの原則について読むことができます。スコットハンセルマンは、これらの原則に関するポッドキャストでボブおじさんにインタビューしました。
これらの原則は、仲間と読んで話し合う良い出発点です。原則が相互に絡み合ったり、懸念の分離や依存性注入などの他のプロセスと相互に作用していることに気付くかもしれません。しばらくTDDを行った後、これらの原則が実際に実際に適用される場合もあります。これは、分離された繰り返し可能な単体テストを作成するためにある程度従う必要があるためです。
デザインパターンの作者自身が最も心配したのは「ビジター」パターンでした。
これは「必要な悪」ですが、頻繁に使用されすぎており、その必要性から設計の根本的な欠陥が明らかになることがよくあります。
「Visitor」パターンの代替名は「Multi-dispatch」です。Visitorパターンは、単一タイプのディスパッチOO言語を使用して、2つのタイプに基づいて使用するコードを選択するときに最終的に使用されるものだからです。 (またはそれ以上)異なるオブジェクト。
典型的な例としては、2つの形状の間に共通部分があるが、見過ごされがちなさらに単純なケースがあります。2つの異種オブジェクトの等価性を比較することです。
とにかく、多くの場合、次のような結果になります。
interface IShape
{
double intersectWith(Triangle t);
double intersectWith(Rectangle r);
double intersectWith(Circle c);
}
これの問題は、「IShape」のすべての実装を結合したことです。階層に新しい形状を追加する場合は常に、他のすべての「形状」実装も変更する必要があることを示唆しています。
時々、これは正しい最小限のデザインです-しかしそれを熟考してください。あなたのデザインは本当に 2つのタイプでディスパッチする必要があることを義務付けていますか?マルチメソッドの組み合わせの爆発のそれぞれを書いてもいいですか?
多くの場合、別の概念を導入することで、実際に記述しなければならない組み合わせの数を減らすことができます。
interface IShape
{
Area getArea();
}
class Area
{
public double intersectWith(Area otherArea);
...
}
もちろん、状況によって異なります-場合によっては、これらのさまざまなケースをすべて処理するためにコードを作成する必要がある場合もありますが、思い切って検討し、Visitorを使用する前に検討する価値があります。それは後であなたに多くの苦痛を保存するかもしれません。
シングルトン-シングルトンXを使用するクラスは、依存関係があり、テストのために見たり分離したりすることが困難です。
便利で理解しやすいため、よく使用されますが、テストが非常に複雑になる場合があります。
シングルトンは病理学的嘘つきを参照してください。
テンプレートメソッドのパターンは一般的に非常に危険なパターンだと思います。
デザインパターン(DP)を避けてはいけないと思います。また、アーキテクチャを計画するときに、自分でDPを使わせてはいけないと思います。計画から自然に生まれた場合にのみ、DPを使用する必要があります。
最初から特定のDPを使用することを定義した場合、将来の設計決定の多くはその選択によって影響を受けるため、選択したDPがニーズに適しているとは限りません。
また、DPを不変のエンティティとして扱い、パターンをニーズに適合させる必要があります。
要約すると、私たちはDPを避けるべきではないと思います。DPがすでに私たちのアーキテクチャで形を成しているとき、それらを採用するべきです。
Active Recordは、ビジネスロジックと永続化コードの混合を促進する使いすぎのパターンだと思います。これは、モデル層からストレージ実装を隠すという非常に優れた仕事をせず、モデルをデータベースに結び付けます。テーブルデータゲートウェイ、行データゲートウェイ、データマッパーなど、多くの代替手段(PoEAAで説明)があり、これらは多くの場合、より優れたソリューションを提供し、ストレージへのより良い抽象化を提供するのに役立ちます。また、モデルをデータベースに保存する必要はありません。それらをXMLとして保存したり、Webサービスを使用してアクセスしたりするにはどうすればよいですか?モデルのストレージメカニズムを変更するのは簡単ですか?
とはいえ、Active Recordは必ずしも悪いわけではなく、他のオプションではやり過ぎるような単純なアプリケーションに最適です。
それは簡単です... あなたにははっきりしないデザインパターンや、快適に感じられないデザインパターンを避けてください。
名前を付けるには...
たとえば、次のような実用的でないパターンがあります。
Interpreter
Flyweight
把握しにくいものもあります。例:
Abstract Factory
-作成されたオブジェクトのファミリーを持つ完全な抽象的なファクトリーパターンは、それがそうであるようにそれほど簡単ではありませんBridge
-抽象化と実装がサブツリーに分割されている場合、抽象化しすぎる可能性がありますが、場合によっては非常に使いやすいパターンですVisitor
-二重発送メカニズムの理解は本当に必須ですひどくシンプルに見えるパターンもいくつかありますが、その原理や実装に関連するさまざまな理由により、あまり明確ではありません。
Singleton
-実際には完全に悪いパターンではなく、過度に使用されすぎている(多くの場合、適切ではない)Observer
-優れたパターン...コードの読み取りとデバッグをはるかに困難にしますPrototype
-コンパイラチェックのダイナミズムをチェックします(これは良いか悪いか...依存します)Chain of responsibility
-強制的または人工的に設計に押し込まれることが多すぎるそれらの「非実用的なもの」については、どこかに通常よりエレガントな解決策があるので、それらを使用する前に本当に考える必要があります。
「把握しにくい」ものについては...適切な場所で使用され、適切に実装されている場合は非常に役立ちますが、不適切に使用されていると悪夢になります。
さて、次は...
私はこれであまり殴られないことを望みます。Christer Ericssonは、リアルタイムの衝突検出ブログで、設計パターンのトピックについて2つの記事(1つ、2つ)を書いています。彼の口調はどちらかといえば過激で、おそらく少し挑発的ですが、男は彼のことを知っているので、狂人のからかいとしてそれを無視するつもりはありません。
一部の人は、サービスロケータは反パターンであると言います。
オブザーバーパターンには多くの答えが必要であると思います。非常に一般的なケースで機能しますが、システムが複雑になると悪夢になり、OnBefore()、OnAfter()通知が必要になり、再同期を回避するために非同期タスクをポストすることがよくあります。入り込み。より優れたソリューションは、計算中にすべてのオブジェクトアクセス(読み取りバリアを使用)を計測し、依存関係グラフにエッジを自動的に作成する自動依存関係分析システムを開発することです。
Spoikeの投稿の補足であるRefactoring to Patternsは良い読み物です。
イテレーターは回避すべきもう1つのGoFパターンであり、少なくとも代替手段がない場合にのみ使用します。
代替案は次のとおりです。
for-eachループ。この構造はほとんどの主流言語に存在し、ほとんどの場合、反復子を回避するために使用できます。
LINQまたはjQueryのセレクター。コンテナのすべてのオブジェクトを処理する必要がないため、for-eachが適切でない場合に使用する必要があります。イテレータとは異なり、セレクタでは、処理するオブジェクトの種類を1か所に明示できます。
yield
イテレータによって可能になったと思います。エリックホワイトは、C#3.0でこれについていくつかの素晴らしい議論があります:blogs.msdn.com/b/ericwhite/archive/2006/10/04/…。また、イテレータを使用したコルーチンに関するJeremy Liknessのディスカッションも確認してください:wintellect.com/CS/blogs/jlikness/archive/2010/03/23/…。