プロキシ、デコレーター、アダプター、ブリッジ パターンはどのように異なりますか?
-
20-08-2019 - |
質問
私はプロキシ パターンを見ていましたが、デコレータ、アダプタ、ブリッジ パターンに非常によく似ているように思えます。私は何かを誤解していますか?違いは何ですか?他のパターンではなく、なぜプロキシ パターンを使用するのでしょうか?過去に現実世界のプロジェクトでそれらをどのように使用しましたか?
解決
Proxyデコレータ、アダプター、ブリッジバリエーション全てに"包装"のクラスです。その用途は異なります。
プロキシ きたい場合に使用しlazy-インスタンスを生成するオブジェクトを非表示にすることまで呼び出すリモートサービスへのアクセスを制御オブジェクトです。
デコレータ とはいえないものはスマートProxy." これはたい場合に使用し機械によるオブジェクトについて、拡張オブジェクトのタイプです。することができますか。
アダプター る場合に使用する抽象インタフェースとしたい地図をインターフェース別のオブジェクトに類似している機能的役割が異なるインターフェース。
橋 似アダプタになっている橋を定義するときの抽象インタフェースと配下の実装です。I.。のない方に対応一部のレガシーまたは第三者コード、デザイナーのすべてのコードが必要でスワップ受けられるようになる実装.
ファサード 高レベル(読み:簡単な)インターフェースをサブシステムはます。い複雑な概念を必要とする複数のオブジェクトを表す。を変更することのセットを提供するものであるかがい知れるオブジェクトのメソッドに必要な金がかかる場合があります。このプログラミングの時間は、ファサードを提供する高レベルの方法は、すべての複雑な操作を試してみましょう。は、オブジェクトのコレクション.例:ドメインモデルのための学校、方法など
countStudents()
,reportAttendance()
,assignSubstituteTeacher()
, います。
他のヒント
では、その構造物です。
プロキシ や デコレータ 両方とも同じ大規模シミュレーションを行い、その包みがプロキシインスタンスを作成し背後にある実装では、デコレータがインスタンスのコンストラクタです。
アダプター や ファサード 両ェのようです。そのアダプターから既存のインタフェースは、ファサードを新しく作成しインターフェース。
橋 や アダプター 両方の点で既存のタイプです。そのブリッジポイント抽象タイプのアダプタがポイントコンクリートタイプです。橋を可能にする一対の実装実行時には、アダプタには通常はしない
私のです。
すべての四つのパターンの多くに共通っていることがすでに分かっていることもあり非公式というラッパー、ラッパーパターンすべての利用組成物、包装対象委託の対象時点のマッピングを行う一つのメソッド呼び出すことがありますか。その予備お客様の必要性を構築し、異なるオブジェクトおよびコピーすべての関連データです。使用する場合は賢明も保存メモリプロセッサー
を推進し、ゆったり結合う一度に安定したコードされてさえも変化を余儀なくされ、読みやのための研究員。
アダプター
アダプター対応(adaptee)の異なるインターフェース。このように当社ブログにアクセスいただきオブジェクトに配置するコレクションの名目的には異なる種類です。
アダプターなだけに該当する方法クライアントで制限する他のすべてを明らかに使用意図の特定のコンテキストのように適応外部ライブラリですることもある一般より当社のアプリケーションのニーズ.アダプターの増加が読みやすさと自己説明のコードです。
アダプターのシールドひとつのチームからの揮発性コードから他のチーム;命を救い主のツールを扱う際に海外のチーム;-)
下記の目的を防止するためのクラスから過剰のアンソロジー。多くの枠組みのアノテーションに基づくことが重要な使用します。
アダプターするJavaの制限からコミュニケーションを継承関係を示します。できるいくつかのadapteesの下を一括して任意の封筒に入れを印象の複数の継承関係を示します。
コードは、アダプターは"薄い".では加えないでくコードをadapteeクラスまでの呼び出しadaptee方法、時折データの変換が必要になります。
多くはありませんの良いアダプタの例では、JDKには基本的な図書館です。アプリケーション開発者をアダプタに順応するために図書館アプリケーション固有のインタフェース
デコレータ
デコレータは代表、地図の方法のひとつにもなり、変更行動の対象方法、を決めることができませ------------対象の方法は、委譲の異なるオブジェクトのヘルパーオブジェクトです。
デコレータは、通常、追加(透明)機能に包まれたオブジェクトのようなロギング、暗号化、フォーマット、または圧縮します。この新しい機能を持参していくつかの新しいコードです。そのため、デコレータは、通常、いくら"fatter"そのアダプタ
デコレータでなければなサブクラスのインタフェース。使用可能で透明なのです。見BufferedOutputStreamで、このOutputStreamとして使用できます。ることが大きな技術的な差異からのアダプタ
文書の例全体のデコレータ族を容易に入手することがでJDKのJava IO.すべてのクラスのように BufferedOutputStream, FilterOutputStream や ObjectOutputStream てデコレータの OutputStream.できるオニオン層は、一つのデコレータが飾られ、加可能です。
プロキシ
プロキシではない典型的なラッパー.に包まれたオブジェクトでは、プロキシ題がまだ存在していない時代。代理人が作成されます。で重オブジェクトで作成した需要、またはそれらのリモートオブジェクトの異なるJVMは異なるネットワークノードとしても非Javaオブジェクトの場合、コンポーネントはネイティブコードです。についての必要なラップまたは委譲を別のオブジェクトです。
最も典型的な例は、リモートプロキシは、重オブジェクトinitializersアクセスプロキシ.
リモートプロキシはリモートサーバは、JVMも非 Javaシステム。プロキシを変換しメソッドの呼び出しにRMI/REST/SOAPで通話や 何が必要な遮蔽お客様からの暴露の基盤となる 技術です。
Lazy負荷代理–完全に初期化オブジェクトのみの利用もしくは 最初に集中す。
アクセスプロキシへのアクセスを制御します。
ファサード
ファサードと密接に連携デザイン原理の少なくとも知法のデメーテル).ファサードはアダプター。その両方を包む人がこれからの地図の一つのオブジェクトに対し、別のものと異なるの意図するだけでも構いません。ファサード偏平に複雑な構造を対象に、複雑なオブジェクト、グラフを簡略化へのアクセスは複雑な構造です。
ファサードはラップの複雑な構造を提供し、平インターフェースです。ことクライアントオブジェクトにさらされているせいで、すっか内部関係の対象構造が推進でゆったりカップリングです。
橋
より複雑な変形アダプターのパターンだけではなく実施りも可能です。で追間接指定します。の代表団は、橋があります。で分離アダプタからでも対応インタフェース。そのために、この複雑さによるその他の包装のパターンです。
の違いのコンストラクタ
パターンの違いも明らかで見ると、そのコンストラクタ.
プロキシ な包装、既存のオブジェクトです。よりコンストラクタです。
デコレータ や アダプター はラップと、既存のオブジェクトは、このような一般的
のコンストラクタです。ファサード コンストラクタ間のルート要素の全体オブジェクトのグラフは、そうでない場合は見え 同じアダプター。
実生活の例– JAXB整列化アダプター.このアダプタをマッピングの単純平のクラスにより複雑な構造に必要な外部からの予防"汚染"subjectクラスは、過度のアンソロジー。
すべての良いられていな開発のためのパターンはます。
ま 飾る 重点が置かれている。
デコレータ:
- 追加の動きもオブジェクト実行時に.相続のキーをこの機能は、両方の長所-短このパターンです。
- で変数を変更する機能を提供する 行動 のインタフェース。
例えば(chaining): java.io
パッケージに関連するクラス InputStream
& OutputStream
界面
FileOutputStream fos1 = new FileOutputStream("data1.txt");
ObjectOutputStream out1 = new ObjectOutputStream(fos1);
任代理人
- 使用しのぐさの初期化機能の改善によるキャッシュのオブジェクトへのアクセス制御は、クライアント呼び出し側.で提供する代替行動やリアルオブジェクトです。この過程で新しいオブジェクトです。
- とは異なり デコレータ, できるチェーンオブジェクトプロキシ なchaining.
例えば: java.rmi
パッケージ。
アダプタ:
- この二つの関係のないインタフェースとは異なるオブジェ, あ再生じます。
- で変更独自のインタフェース.
例えば java.io.InputStreamReader
(InputStream
を返します Reader
)
橋梁:
- この抽象化および実装により独立.
- 使用す 組成物間相続.
例えばコレクションクラスに java.util
. List
実施する ArrayList
.
キーノー:
- アダプター 提供さの異なるインターフェース、。 プロキシ と同様のインタフェース。 デコレータ 提供の強化インタフェース。
- アダプター 変更オブジェクトのインタフェース デコレータ 強化オブジェクトの責任です。
- デコレータ や プロキシ 異なる目的にも類似の構造
- アダプター らくらい、 橋 このような仕事です。
- 橋 設計フローのように抽象化の実装が異なります。 アダプター は補強したく関係のない授業と
- デコレータ する設計ですが、追加責任を果オブジェない場合は、サブクラス.
いでSE質問/記事に関する事例の多様なデザインパターン
これらは非常に似ており、それらの間の線はかなり灰色です。を読むことをお勧めします プロキシパターン そして デコレータパターン c2 wiki のエントリ。
そこにあるエントリと議論は非常に広範であり、他の関連記事へのリンクもあります。ちなみに、異なるパターン間のニュアンスが気になる場合には、c2 wiki が最適です。
c2 エントリを要約すると、デコレーターは動作を追加/変更しますが、プロキシはアクセス制御 (遅延インスタンス化、リモート アクセス、セキュリティなど) に関係していると言えます。しかし、先ほども言ったように、それらの間の線は灰色であり、簡単にデコレータとみなされる可能性のあるプロキシへの参照が見られます。また、その逆も同様です。
これはからの引用です ヘッドファーストデザインパターンの
の定義は、予約に属します。例としては、私に属します。
の のデコレータは - インターフェイスを変更しますが、責任を追加しません。あなたは車のインタフェースを持っていると仮定し、 あなたが車の異なるモデル(S、SV、SL)のためにこれを実装するときは、一部のモデルのためののを追加し、より責任が必要な場合があります。サンルーフ、エアバッグなどを持っている..
のようにのアダプタの - 別のインターフェイスに変換します。あなたは車のインターフェースを持っていて、それがジープのように行動したいと思います。だから、車を取り、それを修正し、ジープに変わります。それは本当のジープではありませんので、<強いです>。しかし、ジープのような役割を果たします。の
の外観の - インターフェイスが簡単になります。あなたは車、飛行機、船のインターフェースを持っていると仮定します。実際にあなたが必要とするすべては、ある場所から別の場所に人々を送信するクラスです。あなたは何を使用するかを決める車両のファサードたいです。そして、あなたはすべてのそれらのインタフェース参照は1つの傘の下を収集し、それをシンプルに保つために/デリゲートを決定させます。
ヘッドファースト:「ファサードは、インタフェースを簡素化するだけでなく、それはサブシステムからクライアントを分離 コンポーネントの。 ファサードとアダプタは、複数のクラスをラップするかもしれないが、ファサードの意図は一方で、簡素化することです アダプタの別の何かへのインタフェースを変換することです。」
すべてのパターンな包装内部のオブジェクトまたはクラスの外からかもしれないけど、僕も同様の構造.私の概要差の目的:
- プロキシ カプセル化してアクセス外です。
- デコレータ 変更または拡大する行動の内と外.
- アダプタ に変換しますからインタフェース内外.
- 橋 分離の不変部分の挙動(外側)からの変数またはプラットフォームに依存する部分(内側).
による界面と内側と外側のオブジェクト
- に プロキシ インタフェースは同じです。
- に デコレータ インタフェースは同じです。
- に アダプタ インタフェースが異なる正式なものを満たす同じ目的です。
- に 橋 インタフェースが異なる概念的に整理.
使っても非常に多くが消費するwebサービスプロキシンパターンもに名称変更前のように、実践的で、いラッパーパターン".また図書室ではプロキシのプログラムを作成します。でも容易に自動化できるExcelな背景などの詳細は何版がインストールされます。
詳細の実装を言えば、私はプロキシとデコレーター、アダプター、ファサードの違いを見つける...これらのパターンの一般的な実装では、囲んでいるオブジェクトによってラップ対象オブジェクトがあります。クライアントではなく、ターゲットオブジェクトのオブジェクトを囲む使用しています。そして、ターゲットオブジェクトは、実際にオブジェクトを囲むの方法のいくつかの内部の重要な役割を果たしています。
ただし、プロキシの場合には、オブジェクトを囲むと、クライアントは、それがターゲットオブジェクトがに参加する必要がありますいくつかのメソッドを呼び出したときに、それだけで対象オブジェクトを初期化し、それ自体でいくつかの方法を再生することができます。これは、遅延初期化です。他のパターンの場合には、封入オブジェクトを仮想対象物に基づいています。だから、オブジェクトは常にコンストラクタ/セッターでオブジェクトを囲むと一緒に初期化され、ターゲットます。
もう一つは、プロキシは、他のパターンを対象とする多くの機能を追加する一方で、ターゲットが何をするのかを正確に行います。
付け加えたいと思い例請求Karwingえることができるね.) を追加するもの鍵を差を実施することを感じている不
引用部品からの回答[https://stackoverflow.com/a/350471/1984346] (Bill Karwing)
Proxyデコレータ、アダプター、ブリッジバリエーション全てに"包装"のクラスです。その用途は異なります。
- プロキシ きたい場合に使用しlazy-インスタンスを生成するオブジェクト という事実を隠すだけで呼び出すリモートサービス、またはアクセス制御 のオブジェクトです。
ProxyClassとObjectClassる場合にのみ有用で、実は同じインタフェースなどに入れ換え可能
例-プロキシの高価なオブジェクト
class ProxyHumanGenome implements GenomeInterface {
private $humanGenome = NULL;
// humanGenome class is not instantiated at construct time
function __construct() {
}
function getGenomeCount() {
if (NULL == $this->humanGenome) {
$this->instantiateGenomeClass();
}
return $this->humanGenome->getGenomeCount();
}
}
class HumanGenome implement GenomeInterface { ... }
- デコレータ とはいえないものはスマートProxy." この場合に使用したい 追加機能をオブジェクトについて、拡張オブジェクトの タイプです。することができますか。
DecoratorClassべきであるが実施と拡張インターフェイスのObjectClass.そのObjectClassで置き換えることができますDecoratorClassがない。
例-追加機能
class DecoratorHumanGenome implements CheckGenomeInterface {
// ... same code as previous example
// added functionality
public function isComplete() {
$this->humanGenome->getCount >= 21000
}
}
interface CheckGenomeInterface extends GenomeInterface {
public function isComplete();
}
class HumanGenome implement GenomeInterface { ... }
- アダプター る場合に使用する抽象インタフェースとしたい 地図インタフェース別のオブジェクトに類似している機能 役割が異なるインターフェース。
Implentationの違いは、プロキシやデコレータ、アダプター
アダプターの異なるインターフェース、。プロキシと同様のインタフェース。デコレーターの強化インタフェース。
橋 似アダプタま橋き 定義の両方を抽象インタフェースと配下の実装です。I.。のない方に対応一部のレガシーまたは第三者コード、 デザイナーのすべてのコードが必要で交換 異なる実装.
ファサード 高レベル(読み:簡単な)インターフェースをサブシステム ります。い複雑な概念を必要とする 複数のオブジェクトを表す。変更にこのオブジェクト はくがいかのオブジェクトの 方法が必要金がかかる場合があります。このプログラミングの時間は、ファサードと 高レベルの方法は、すべての複雑な操作できない のオブジェクトのコレクション.例:ドメインモデルのための学校 マスタープランの第一の方法
countStudents()
,reportAttendance()
,assignSubstituteTeacher()
, います。
もっと詳しい情報はこの答えは https://sourcemaking.com/design_patterns, をお勧めして 優れた資源 デザインパターン
私は、コードは(だけでなく、他の答えを補完するために)明確なアイデアを与えるだろうと考えています。 (クラスの実装とラップタイプフォーカス)、以下を参照してください。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
/* Proxy */
Console.WriteLine(Environment.NewLine);
Console.WriteLine("PROXY");
Console.WriteLine(Environment.NewLine);
//instead of creating here create using a factory method, the facory method will return the proxy
IReal realProxy = new RealProxy();
Console.WriteLine("calling do work with the proxy object ");
realProxy.DoWork();
Console.WriteLine(Environment.NewLine);
Console.WriteLine("ADAPTER");
Console.WriteLine(Environment.NewLine);
/*Adapter*/
IInHand objectIHave = new InHand();
Api myApi = new Api();
//myApi.SomeApi(objectIHave); /*I cant do this, use a adapter then */
IActual myAdaptedObject = new ActualAdapterForInHand(objectIHave);
Console.WriteLine("calling api with my adapted obj");
myApi.SomeApi(myAdaptedObject);
Console.WriteLine(Environment.NewLine);
Console.WriteLine("DECORATOR");
Console.WriteLine(Environment.NewLine);
/*Decorator*/
IReady maleReady = new Male();
Console.WriteLine("now male is going to get ready himself");
maleReady.GetReady();
Console.WriteLine(Environment.NewLine);
IReady femaleReady = new Female();
Console.WriteLine("now female is going to get ready her self");
femaleReady.GetReady();
Console.WriteLine(Environment.NewLine);
IReady maleReadyByBeautician = new Beautician(maleReady);
Console.WriteLine("now male is going to get ready by beautician");
maleReadyByBeautician.GetReady();
Console.WriteLine(Environment.NewLine);
IReady femaleReadyByBeautician = new Beautician(femaleReady);
Console.WriteLine("now female is going to get ready by beautician");
femaleReadyByBeautician.GetReady();
Console.WriteLine(Environment.NewLine);
Console.ReadLine();
}
}
/*Proxy*/
public interface IReal
{
void DoWork();
}
public class Real : IReal
{
public void DoWork()
{
Console.WriteLine("real is doing work ");
}
}
public class RealProxy : IReal
{
IReal real = new Real();
public void DoWork()
{
real.DoWork();
}
}
/*Adapter*/
public interface IActual
{
void DoWork();
}
public class Api
{
public void SomeApi(IActual actual)
{
actual.DoWork();
}
}
public interface IInHand
{
void DoWorkDifferently();
}
public class InHand : IInHand
{
public void DoWorkDifferently()
{
Console.WriteLine("doing work slightly different ");
}
}
public class ActualAdapterForInHand : IActual
{
IInHand hand = null;
public ActualAdapterForInHand()
{
hand = new InHand();
}
public ActualAdapterForInHand(IInHand hnd)
{
hand = hnd;
}
public void DoWork()
{
hand.DoWorkDifferently();
}
}
/*Decorator*/
public interface IReady
{
void GetReady();
}
public class Male : IReady
{
public void GetReady()
{
Console.WriteLine("Taking bath.. ");
Console.WriteLine("Dress up....");
}
}
public class Female : IReady
{
public void GetReady()
{
Console.WriteLine("Taking bath.. ");
Console.WriteLine("Dress up....");
Console.WriteLine("Make up....");
}
}
//this is a decorator
public class Beautician : IReady
{
IReady ready = null;
public Beautician(IReady rdy)
{
ready = rdy;
}
public void GetReady()
{
ready.GetReady();
Console.WriteLine("Style hair ");
if (ready is Female)
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine("doing ready process " + i);
}
}
}
}
}
デザインパターンは、それが芸術とソフトウェア工学の組み合わせであり、数学ではありません。プロキシを使用する必要があり、このためのrequirmentのように何もない、橋などのデザインパターンは、問題を解決するために作成されますがあります。あなたは、設計上の問題が予想される場合は、それを使用しています。経験に基づいて、パターンを使用するか、特定の問題のために知るようになります。あなたが固体の設計原理に優れている場合、あなたはそれがパターンです知らなくてもデザインパターンを実装しているでしょう。一般的な例としては、statergy、工場のパターンである。
そこで固体desighn原理、クリーン符号化原則及びTTDについての集中