デザインパターンの7つの原則
- 開閉の原則:拡張のために開き、変更のために閉じます。
- 単一の告発の原則:クラスは1つのことだけを行います。
- 反転の原則に依存します。iocと同様に、インターフェイスプログラミングを使用します。
- ディミットの原理:高い凝集度、低い結合度。
- インターフェイス分離の原則:単一の合計インターフェイスではなく、複数のインターフェイスを使用する必要があります。
- 複合再利用の原則:再利用の目的を達成するために、継承の代わりにオブジェクトコンポジションを使用するようにしてください。
- リスコフ置換の原則:サブクラスは親クラスの関数を拡張できますが、元の関数を変更することはできません。
1.作成モード(5種類)
1.シングルトンモード(シングルトン)
クラスのインスタンスが1つしかないことを確認し、グローバルアクセスポイントを提供します。
4つのシングルトン実装方法があります:https://blog.csdn.net/sumengnan/article/details/108958904
2.ファクトリモード(ファクトリ)
デカップリングの目的を達成するために、オブジェクト作成機能をファクトリに提供します。
シーンに適しています:
- オブジェクトの正確なタイプと依存関係を予測できない場合に使用できます。
- 毎回オブジェクトを作成するのではなく、既存のオブジェクトを再利用してシステムリソースを節約したいと考えています。
3.抽象ファクトリモード(抽象ファクトリ)
特定のクラスを指定せずに一連の関連オブジェクトを作成するために使用されます
シーンに適しています:
- コードが複数の異なる一連の関連製品と相互作用する必要がある場合、事前に関連情報を取得できないため、または将来の拡張の考慮事項のため、コードが製品の特定のクラスに基づいて構築されるときに使用されることは期待されません。
- 一連の抽象メソッドに基づくクラスがあり、その主な機能が明確でない場合に使用できます。
ユースケース: SpringのBeanFactory。そして、オブジェクトを作成するために使用されるが、インターフェースまたは抽象クラスを返す他のものはすべてこのパターンです。
マッチングモード:戦略モード
4.ビルダーモード(ビルダー)
複雑なオブジェクトの作成を簡素化するクラスを定義します(段階的な作成)。このクラスは、別のクラスのインスタンスを構築するためのものです。
シーンに適しています:
- 「重複するコンストラクター」の出現は避けてください。
- コードを使用してさまざまな形式の製品を作成する場合に使用します。
- たとえば、注文システムでは、注文オブジェクトは複雑なオブジェクトであり、それを構築できます。
ユースケース: SpringApplicationBuilder、StringBuilder
5.プロトタイプ
コードをそれらが属するクラスに依存させることなく、既存のオブジェクトをコピーできます。
シーンに適しています:
- オブジェクトのインスタンスの作成は非常に複雑で時間がかかり、使用できます
- たとえば、変換時にDTO、BO、DO、VOを使用できます
ユースケース: Spring Beanにはシングルトンモードとプロトタイプモードがあります(スコープ=プロトタイプ)
2、構造モード(7タイプ)
1.プロキシモード(プロキシ)
プロキシは元のオブジェクトへのアクセスを制御し(元のオブジェクトに直接アクセスすることはできません)、リクエストがオブジェクトに送信される前後に何らかの処理を許可します。
シーンに適しています:
- 元のオブジェクトを保護するために使用されます
- 元のオブジェクトを拡張するために使用されます
ユースケース: jdkのプロキシクラス
2.アダプタモード
これは、新しいインターフェイスと古いインターフェイスを適合させるために使用され、互換性のないインターフェイスを持つオブジェクトが相互に連携できるようにします。
シーンに適しています:
- 特定のクラスを使用したいのですが、インターフェースや他のコードと互換性がありません。
ユースケース: springmvcのHandlerAdapter。たとえば、xmlからjsonは、新しいXmlJsonAdapterアダプタークラスで変換できます。
3.ブリッジモード(ブリッジ)
抽象的および抽象的具体的実現を分離することにより、抽象的および抽象的具体的実現を独立して変更することができます。そして、組み合わせの方法を使用して、多次元の抽象メソッドをリンクします
シーンに適しています:
- 複数の関数(たとえば、データと対話できる複数のクラス)を持つ複雑なクラスを分割または再編成する場合は、使用できます。
- クラスをいくつかの緯度に拡張したい。
- 実行中に異なる実装方法を切り替えたい。
4.コンビネーションモード(コンポジット)
これを使用して、オブジェクトをツリー構造に結合し、「部分全体」の階層構造を表すことができ、独立したオブジェクトのように使用できます。
単一のオブジェクトとオブジェクトの組み合わせを処理するときに、クライアントが等しいように見えるようにします。つまり、特定のタイプのメソッドは、それ自体のタイプもパラメーターとして受け入れます。たとえば、MapのputAll(Map)メソッド
シーンに適しています:
- 木のようなオブジェクト構造を実現する必要があります。
- クライアントコードで単純な要素と複雑な要素を同じように処理する場合。
- 多くの場合、再帰操作の最適化に使用されます
例:
5.外観モード/ファサードモード(ファサード)
一連のインターフェース、抽象クラス、またはサブシステムに簡略化されたインターフェースを提供します。また、サブシステムの外部と内部の間の通信は、統合されたファサードオブジェクトを介して実行する必要があります。
ファサードモードは高レベルのインターフェイスを提供し、サブシステムを使いやすくします
シーンに適しています:
- 複雑なサブシステムへの直接インターフェースが必要であるが、使用される機能が制限されている場合。
- サブシステムが多層構造として編成されている場合。
- サブシステムのインターフェースを保護するために、ファサードモードを使用して、すべてではなく一部のインターフェースのみを提供できます。
- Dubboを使用すると、外部から提供されるサービスは可能な限りファサードモデルを採用する必要があります。その後、サービスはさまざまなサービスを呼び出して集約します。
例:
- tomcat的RequestFacade
- SLFJログはファサードログです
6.デコレーションモード(デコレータ/ワッパー)
ビヘイビアーを含む特別なカプセル化されたオブジェクトにオブジェクトを配置することにより、新しいビヘイビアーを元のオブジェクトにバインドします。これは、オブジェクトに追加の関数を動的にアタッチすることと同等であるため、サブクラス化の代替手段でもあります。
例:
- TomcatのリクエストラッパーServletRequestWrapper
- すべてのioストリームラッパー
7.フライ級
各オブジェクトにすべてのデータを格納する方法を放棄し、複数のオブジェクトによって共有される同じ状態を共有することにより、限られたメモリ容量でより多くのオブジェクトをロードできるようにします。
簡単に言えば、キャッシュを使用してオブジェクトのアクセス時間を短縮することです(共有テクノロジーを使用して要素の共有を実現します)
シナリオに適しています:プログラムは多数のオブジェクトをサポートし、十分なメモリ容量(共有変数)がない場合に使用する必要があります
例:
-
キャッシュが使用されている限り、フライウェイトモードが基本的に使用されます
3.行動モデル(12種類)
1.責任の連鎖(責任の連鎖)
プロセッサチェーンに沿ってリクエストを送信します。要求を受信した後、各プロセッサは要求を処理するか、チェーン上の次のプロセッサに渡すことができます。
デカップリングを実現できます。責任の連鎖内のオブジェクトは、同じインターフェースまたは抽象クラスの異なる実装です。
シーンに適しています:
- プログラムがさまざまな要求をさまざまな方法で処理する必要があり、要求のタイプと順序が不明な場合。
- 複数のプロセッサを順番に実行する必要がある場合。
- 必要なプロセッサとその順序を実行時に変更する必要がある場合。
用例:
servler中Filter过滤器
拦截器等
2.コマンドモード(コマンド)
コマンドをオブジェクトにラップして、他のオブジェクトと同じように保存してメソッドに渡し、返すことができるようにします(クラス名としてコマンドアクションを使用)
コマンドモードでは、コマンドを発行する責任とコマンドを実行する責任を分離できます。
シーンに適しています:
- オブジェクトは、操作を通じてパラメーター化する必要があります。
- 操作をキューに入れて、ローカルまたはリモートで操作を実行する場合に使用できます。
- 操作ロールバック機能を実装したい場合。
用例:
java.lang.Runnable
javax.swing.Action
3.イテレータモード(イテレータ)
コレクションの基礎となる表現(リスト、スタック、ツリーなど)を公開せずに、コレクション内のすべての要素をトラバースできます。
コレクション内のオブジェクトにアクセスするための統一された方法を提供します。
シーンに適しています:
- コレクションの背後にある複雑なデータ構造の場合、クライアントからそれを非表示にする必要があります(利便性またはセキュリティのため)
- プログラム内で繰り返されるトラバーサルコードを監視できます
- 異なる、さらには予測不可能なデータ構造をトラバースしたい場合。
用例:
- イテレータ
- ベクトルコレクション
- セットコレクション
4.調停人
オブジェクト間の無秩序で無秩序な依存関係を減らすことができます。このモードは、オブジェクト間の直接の相互作用を制限し、中間オブジェクトを介してオブジェクトを強制的に連携させます。(中間オブジェクトを使用して、一連のオブジェクトの相互作用動作をカプセル化します)
つまり、メッセージ配信に中間オブジェクトを使用し、クラス間の直接の依存関係を減らします
シーンに適しています:
- 一部のオブジェクトまたは他のオブジェクトが緊密に結合されており、変更が難しい場合。
- コンポーネントが他のコンポーネントに依存しすぎて、別のアプリケーションで再利用できない場合。
- さまざまなシナリオでいくつかの基本的な動作を再利用できるようにするために、多数のコンポーネントサブクラスを作成することを強制する必要があります。
用例:
- mqはこのモードを使用します
- MVCのコントローラー
- エグゼキュータ
5.メメントモード(メメント)
オブジェクトの実装の詳細を公開せずに、オブジェクトの以前の状態を保存および復元できます。
つまり、オブジェクトの状態のスナップショットが生成されるため、オブジェクトは、独自のコンテンツを公開せずに元の状態に復元できます。
カプセル化を破棄せずに、クラスの内部状態をキャプチャして保存し、保存された状態を使用してリカバリ操作を実装できます。
シーンに適しています:
- 以前の状態を復元するためにオブジェクト状態のスナップショットを作成する必要がある場合
- オブジェクトのメンバー変数、get、およびsetに直接アクセスしたときに、カプセル化が壊れた場合
用例:
- Dateオブジェクトは、それ自体の長い値を介してメモモードを実装します
- シリアル化可能
6.オブザーバーモード/パブリッシュおよびサブスクライブモード(オブザーバー/リスナー)
オブジェクトイベントが発生したときにオブジェクトを「監視」する他の複数のオブジェクトに通知できるサブスクリプションメカニズムを定義できます。
シーンに適しています:
- あるオブジェクトの変更で他のオブジェクトを変更する必要がある場合、または実際のオブジェクトが事前に不明であるか、動的に変更される場合。
- アプリケーション内の一部のオブジェクトが他のオブジェクトを監視する必要がある場合。
用例:
- EventListener
- tomcat的LifeCycleListener
- 分散ロック、サービスディスカバリなど、オブザーバーとしてzookeeperを使用します。
7.状態モード(状態)
オブジェクトの内部状態が変化したときの動作を変更して、オブジェクトが属するクラスを変更したように見せることができます。
これにより、内部状態に基づいて実行時にオブジェクトの動作を簡単に変更できます。
状態モードは、さまざまなことを行うために状態を切り替えることに焦点を当てており、状態モードのさまざまな状態で行われることは異なります。
状態パターンはオブジェクトの状態をカプセル化します。状態はオブジェクトと密接に関連しているため、再利用できません。
シーンに適しています:
- オブジェクトが現在の状態に応じて異なる動作をする必要がある場合、状態の数は非常に多く、状態に関連するコードは頻繁に変更されます。
- クラスがメンバー変数の現在の値に基づいて動作を変更する場合。これには、多数の条件ステートメントを使用する必要があります。
- 同様の状態および状態ベースの遷移に重複するコードが多数ある場合
8.ストラテジーモード(ストラテジー)
これにより、一連のアルゴリズムを定義し、各アルゴリズムを個別のクラスに配置して、アルゴリズムのオブジェクトを相互に置き換えることができます。
これは、一連のアルゴリズムを一連のオブジェクトにカプセル化することです。これらのオブジェクトを呼び出すことにより、プログラムの機能を柔軟に変更できます。
戦略モードは、特定の状況に基づいて戦略を選択することに重点を置いており、切り替えは含まれません。戦略モードも同じことをします。
ストラテジーモードは、アルゴリズムまたはストラテジーをカプセル化します。ストラテジーまたはアルゴリズムをコンテキストから分離することにより、それらを再利用できます。
シーンに適しています:
- オブジェクトでさまざまな異なるアルゴリズムバリアントを使用し、実行時にアルゴリズムを切り替えたい場合。
- アルゴリズムがコンテキストのロジックで特に重要でない場合、このパターンを使用すると、クラスのビジネスロジックをアルゴリズムの実装の詳細から分離できます。
- クラスでelseなどの複雑な条件演算子を使用して、同じアルゴリズムの異なるバリアントを切り替える場合。
ストラテジーモードとファクトリモードを使用して、プログラム内の過剰なif-elseを最適化できます
9.テンプレートモード(テンプレート)
アルゴリズムフレームワークはスーパークラスで定義され、サブクラスが構造を変更せずにアルゴリズムの特定のステップを書き換えることができます。
つまり、サブクラスは、リライト全体ではなく、メソッドの一部をリライトできます。サブクラスがリライトする必要のある操作を制御できます。
シーンに適しています:
- アルゴリズム全体やその構造ではなく、クライアントに特定のアルゴリズムステップのみを拡張させたい場合。
- 複数のクラスのアルゴリズムが、若干の違いを除いてほぼ同じである場合。
用例:
- InputStreamクラスのメソッドをスキップまたは読み取る
- 抽象クラスを作成できます。メソッドには、差別化を実現するためのサブクラスが必要です。
10.ビジターモード(ビジター)
オブジェクトのグループを操作するための便利で保守可能な方法を提供します。操作のオブジェクトを変更せずに、オブジェクトの動作を変更または拡張できます。
動作するオブジェクトからアルゴリズムを分離できます。ただし、元のクラス構造を変更せずに新しい関数を追加し続けることができます。しかし、欠点はそれがカプセル化を破壊することです
シーンに適しています:
- 複雑なオブジェクト構造(オブジェクトツリーなど)のすべての要素に対して特定の操作を実行する必要がある場合。
- このモードは、補助動作のビジネスロジックをクリーンアップするために使用できます。
- 特定の動作がクラス階層内の一部のクラスでのみ意味がある場合、他のクラスでは意味がありません。
11.空のオブジェクトモード(空)
これにより、抽象的な空のオブジェクトを処理できます。
用例:
- コレクションクラスのEmptyList()
- コレクションクラスのEmptyMap()
- CollectionsクラスのEmptySet()
12.通訳モード(通訳)
通常、言語が文法を定義し、文法を使用して文を解釈するために記述されます
用例:
- パターンクラス
- ノーマライザークラス
- フォーマットクラス
詳細なデザインパターンについては、https ://refactoringguru.cn/design-patternsを参照してください。