175

ProxyDecoratorの違いは何ですか?

私が見る主な違いは、プロキシ構成を使用し、デコレーター集約を使用すると仮定すると、複数の (1 つ以上の)デコレーターを使用することで、既存のインスタンスに機能を変更/追加 (装飾) できることは明らかです。プロキシには、プロキシされたクラスの独自の内部インスタンスがあり、いくつかの追加機能 (プロキシ動作) を追加して委任します。

問題は、集計で作成されたProxyはまだProxyであるか、それともDecoratorであるかということです。集約を使用してプロキシを作成することは (GoF パターンの定義により) 許可されていますか?

4

10 に答える 10

133

本当の違いは、所有権 (構成と集約) ではなく、型情報です。

デコレータ常にデリゲートに渡されます。プロキシ はそれを自分で作成するか、注入することができます。

しかし、プロキシ は常にデリゲートの (より) 特定のタイプを知っています。つまり、プロキシとそのデリゲートは同じ基本型を持ちますが、プロキシは何らかの派生型を指します。Decoratorは、独自の基本型を指します。したがって、違いはデリゲートの型に関するコンパイル時の情報にあります。

動的言語では、デリゲートが注入され、たまたま同じインターフェイスを持っている場合、違いはありません。

あなたの質問に対する答えは「はい」です。

于 2014-08-08T03:59:07.210 に答える
96

デコレーターパターンは、オブジェクトに関数を動的に追加することに重点を置いていますが、プロキシパターンは、オブジェクトへのアクセスを制御することに重点を置いています。

編集:-

Proxyと実際のサブジェクトの間の関係は通常、コンパイル時に設定され、Proxyは何らかの方法でそれをインスタンス化しますが、Decoratorは実行時にサブジェクトに割り当てられ、サブジェクトのインターフェイスのみを認識します。

于 2013-09-04T16:09:50.380 に答える
4

この答えとそれが実際に何を意味するのかを理解するのにしばらく時間がかかりました. いくつかの例がそれをより明確にするはずです。

Proxy最初:

public interface Authorization {
    String getToken();
} 

と :

// goes to the DB and gets a token for example
public class DBAuthorization implements Authorization {
    @Override
    public String getToken() {
        return "DB-Token";
    }
}

Authorizationそして、かなりばかげたthis の呼び出し元があります:

class Caller {
    void authenticatedUserAction(Authorization authorization) {
        System.out.println("doing some action with : " + authorization.getToken());
    }
}

これまでのところ異常はありませんよね?特定のサービスからトークンを取得し、そのトークンを使用します。ここで、もう 1 つの要件があります。ログを追加します。つまり、毎回トークンをログに記録します。この場合は簡単です。次を作成するだけProxyです。

public class LoggingDBAuthorization implements Authorization {

    private final DBAuthorization dbAuthorization = new DBAuthorization();

    @Override
    public String getToken() {
        String token = dbAuthorization.getToken();
        System.out.println("Got token : " + token);
        return token;
    }
}

それをどのように使用しますか?

public static void main(String[] args) {
    LoggingDBAuthorization loggingDBAuthorization = new LoggingDBAuthorization();

    Caller caller = new Caller();
    caller.authenticatedUserAction(loggingDBAuthorization);
}

のインスタンスをLoggingDBAuthorization 保持していることに注意してくださいDBAuthorizationLoggingDBAuthorizationDBAuthorization 実装 の両方Authorization

  • DBAuthorizationプロキシは、基本インターフェイス ( ) の具体的な実装 ( ) を保持しますAuthorization。言い換えれば、プロキシは何がプロキシされているかを正確に知っています。

Decorator:

Proxyインターフェイスを使用して、 とほとんど同じように開始します。

public interface JobSeeker {
    int interviewScore();
}

そしてそれの実装:

class Newbie implements JobSeeker  {
    @Override
    public int interviewScore() {
        return 10;
    }
}

そして今、より経験豊富な候補者を追加したいと思います。これは、面接のスコアに別のスコアを加えたものJobSeekerです。

@RequiredArgsConstructor 
public class TwoYearsInTheIndustry implements JobSeeker {

    private final JobSeeker jobSeeker;

    @Override
    public int interviewScore() {
        return jobSeeker.interviewScore() + 20;
    } 
}

ではなく、別の JobSeeker からのものに加えて言ったことに注目してください。Aは何を装飾しているのか正確にはわかりません。その装飾されたインスタンスのコントラクトだけを知っています (それは について知っています)。これは;とは異なることに注意してください。対照的に、それが何を飾っているのかを正確に知っています。 NewbieDecoratorJobSeekerProxy

この場合、実際に 2 つの設計パターンに違いがあるかどうか疑問に思われるかもしれません。Decoratorをとして書き込もうとした場合はどうなるでしょうProxyか。

public class TwoYearsInTheIndustry implements JobSeeker {

    private final Newbie newbie = new Newbie();

    @Override
    public int interviewScore() {
        return newbie.interviewScore() + 20;
    }
}

これは間違いなくオプションであり、これらのパターンがどれほど近いかを強調しています。他の回答で説明されているように、それらは依然としてさまざまなシナリオを対象としています。

于 2019-10-24T17:49:25.453 に答える