프록시와 데코레이터 패턴의 차이점


136

프록시데코레이터 의 차이점은 무엇 입니까?

내가 볼 수있는 주요 차이점은 프록시컴포지션을 사용 하고 데코레이터집계 를 사용 한다고 가정 할 때 여러 (하나 이상의) 데코레이터 를 사용하여 기존 인스턴스 (장식)에 기능을 수정 / 추가 할 수 있다는 것이 분명해 보입니다. 프록시 는 프록시 클래스의 내부 인스턴스를 가지고 있으며 추가 기능 (프록시 동작)을 추가하여 위임합니다.

문제는 -합니까 프록시는 집계가 아직 만들어 프록시 또는 오히려 실내 장식 ? GoF 패턴으로 정의 하여 집계 를 사용하여 프록시 를 만들 수 있습니까?



5
Proxy가 컴포지션을 사용하고 Decorator가 집계를 사용한다는 아이디어를 어디서 얻었습니까?
CPerkins

1
@CPerkins는 Rahul Tripathi 답변에 대한 내 의견을 봅니다.
Łukasz Rzeszotarski

1
또한 데코레이터 ( patterns.cs.up.ac.za/examples/ch2/decorator-theory.cs)- 분명히 집계, 프록시 ( patterns.cs.up.ac.za/examples/ch2/proxy-theory.cs ) -분명히 구성.
hyankov

답변:


17

다음은 GoF에서 직접 인용 한 것입니다 (216 페이지).

데코레이터는 프록시와 유사한 구현을 가질 수 있지만 데코레이터는 다른 목적을 가지고 있습니다. 데코레이터는 객체에 하나 이상의 책임을 추가하는 반면 프록시는 객체에 대한 액세스를 제어합니다.

프록시는 데코레이터처럼 구현되는 정도가 다릅니다. 보호 프록시는 데코레이터와 똑같이 구현 될 수 있습니다. 반면에 원격 프록시에는 실제 주제에 대한 직접 참조가 아니라 "호스트 ID 및 호스트의 로컬 주소"와 같은 간접 참조 만 포함됩니다. 가상 프록시는 파일 이름과 같은 간접 참조로 시작하지만 결국 직접 참조를 가져 와서 사용합니다.

인기있는 답변은 대리인이 구체적인 유형의 대리인을 알고 있음을 나타냅니다. 이 인용문에서 우리는 항상 사실이 아니라는 것을 알 수 있습니다.

GoF에 따른 프록시와 데코레이터의 차이점은 프록시 가 클라이언트를 제한 한다는 것입니다. 데코레이터는하지 않습니다. 프록시 클라이언트가 무엇을 제한 할 수 있습니다 않는 기능에 대한 액세스를 제어하여, 또는 고객이 알고있는 것을 제한 할 수 있습니다 보이지 않고 알려지지 않은 작업을 수행 . Decorator는 그 반대입니다. 대리자가 클라이언트가 볼 수있는 방식으로 업무를 향상시킵니다.

우리는 프록시가 블랙 박스이고 데코레이터가 화이트 박스라고 말할 수 있습니다.

래퍼와 델리게이트 간의 컴포지션 관계는 Proxy와 Decorator를 대조 할 때 중점을 두는 잘못된 관계입니다. 컴포지션은이 두 패턴이 공통적으로 갖는 기능이기 때문입니다. 랩퍼와 클라이언트의 관계는이 두 패턴을 차별화하는 것입니다.

  • Decorator는 고객에게 정보를 제공하고 권한을 부여합니다.
  • 프록시는 클라이언트를 제한하고 해제합니다.

113

실제 차이점은 소유권 (구성 대 집계)이 아니라 형식 정보입니다.

실내 장식이 되어 항상 그 위임자을 통과시켰다. 프록시 그것을 자신을 만들거나 그 는 주사 있습니다.

그러나 대리인은 항상 특정 유형의 대리인을 알고 있습니다. 다시 말해, 프록시 와 대리인은 동일한 기본 유형을 가지지 만 프록시는 파생 된 유형을 가리 킵니다. 실내 장식 자신의 기본 유형을 가리키는. 따라서 델리게이트 유형에 대한 컴파일 타임 정보가 다릅니다.

동적 언어에서 대의원이 주입되어 동일한 인터페이스를 갖는 경우 아무런 차이가 없습니다.

귀하의 질문에 대한 답변은 "예"입니다.


2
"그러나 대리인은 항상 (더 많은) 특정 유형의 대리인을 알고 있습니다."나는 그것이 사실이라고 생각하지 않습니다. 원격 프록시를 상상해보십시오. 프록 싱 메커니즘은 원격 객체의 특정 사항을 알 필요가 없습니다. 리모트 시스템은 지정된 인터페이스로 오브젝트를 등록합니다. 로컬 프록시는 동일한 인터페이스를 제공합니다.
Alexey

3
나는 그의 것을 아는 방문 강사로부터 아마존에서 수업을 들었습니다. "프록시"실행 파일 사용 (예 : 웹 서비스 사용)과 프록시 디자인 패턴간에 차이가 있습니다. 프록시 패턴과 데코레이터 패턴의 UML은 다를 수 있습니다. 그러나 프록시가 위임자와 동일한 API를 갖는 것을 막을 수있는 것은 없습니다. Decorator는 프록시의 엄격한 하위 집합이지만 기본 API가 동일한 지 여부에 따라 Decorator를 여전히 프록시라고 수 있습니다.
cdunn2001

85

데코레이터 패턴은 객체에 기능을 동적으로 추가하는 데 중점을 두며 프록시 패턴은 객체에 대한 액세스를 제어하는 ​​데 중점을 둡니다.

편집하다:-

프록시 와 실제 주제 간의 관계 는 일반적으로 컴파일 타임에 설정되고 프록시 는 어떤 방식으로 인스턴스화하는 반면 데코레이터 는 런타임에 주제의 인터페이스 만 알고 주제에 할당됩니다.


5
그래도 프록시를 사용하여 기능을 추가 할 수 있습니다. AOP 프록시를 생각해보십시오.
Sotirios Delimanolis

5
전적으로 동의합니다. 즉, 프록시 패턴을 사용한다는 의미로 프록시 클래스를 변환하면 프록시 클래스가 클라이언트에서 객체의 세부 정보를 숨길 수 있습니다. 따라서 프록시 패턴을 사용할 때 일반적으로 프록시 클래스 내에 abject 인스턴스를 만듭니다. 그리고 Decorator Pattern을 사용할 때, 일반적으로 원본 오브젝트를 매개 변수로 데코레이터의 생성자에 전달합니다.
Rahul Tripathi

이 경우 프록시에서 인스턴스가 '숨겨 짐'인 경우 차이가 분명합니다 (필자가 쓴 것처럼). 나는 종종 사람들이 생성자 매개 변수로 전달 된 프록시 객체를 취하는 프록시 클래스로 호출한다고 생각합니다. 이 경우 새로운 기능 추가 또는 제어의 차이는 (아주) 나에게 얇습니다.
Łukasz Rzeszotarski

5
프록시와 실제 주제 간의 관계는 일반적으로 컴파일 타임에 설정되고 프록시는 어떤 방식으로 인스턴스화하는 반면 데코레이터 또는 어댑터는 런타임에 주제의 인터페이스 만 알고 주제에 할당됩니다. 말이 되길 바래 !!! :)
Rahul Tripathi

1
이 줄을 답에 추가 할 수 있습니다.
Łukasz Rzeszotarski

49

데코레이터 는 장식 된 객체 (일반적으로 생성자를 통해)에 대한 참조를 가져 오지만 프록시 는 직접 그 역할을 담당합니다.

데코레이터가 항상 실제 랩핑 된 인스턴스에 대한 링크를 보유 하는 동안 프록시 는 랩핑 오브젝트를 전혀 인스턴스화하지 않을 수 있습니다 (오브젝트 필드 / 게터가 사용되지 않는 경우 DB에 대한 불필요한 액세스를 방지하기 위해 ORM을 수행함) .

프록시는 일반적으로 프레임 워크에서 보안 또는 캐싱 / 레이 징을 추가하고 프레임 워크별로 구성합니다 (일반 개발자가 아닌).

데코레이터는 일반적으로 실제 클래스가 아닌 인터페이스를 기반으로 개발자가 기존 클래스 또는 레거시 클래스에 새로운 동작을 추가하는 데 사용되었습니다 (따라서 광범위한 인터페이스 인스턴스에서 작동하며 프록시 는 콘크리트 클래스를 중심으로합니다).


22

주요 차이점 :

  1. 프록시 는 동일한 인터페이스를 제공합니다. Decorator 는 향상된 인터페이스를 제공합니다.
  2. 데코레이터프록시 는 목적이 다르지만 구조는 비슷합니다. 둘 다 다른 객체에 대한 간접적 인 수준을 제공하는 방법을 설명하고 구현은 요청을 전달하는 객체에 대한 참조를 유지합니다.
  3. 데코레이터 는 하나의 구성 요소 만있는 축퇴 합성물로 볼 수 있습니다. 그러나 데코레이터는 추가 책임을 추가합니다. . 객체 집계를위한 것이 아닙니다.
  4. 데코레이터 는 재귀 구성을 지원합니다
  5. 데코레이터 클래스는 선언 조성 액정 (최저 등급 분모) 인터페이스에 관계하고,이 데이터가 부재 생성자에서 초기화된다.
  6. 개체를 캐싱 하고 클라이언트 / 호출자에 대한 액세스를 제어 하여 지연 초기화, 성능 향상을 위해 프록시 사용

소스 메이킹 기사는 유사점과 차이점을 훌륭한 방법으로 인용합니다.

관련 SE 질문 / 링크 :

데코레이터 패턴은 언제 사용합니까?

어댑터와 프록시 패턴의 정확한 차이점은 무엇입니까?


3

프록시와 데코레이터는 목적과 내부 구현에 중점을 둔 부분이 다릅니다. 프록시는 원격, 교차 프로세스 또는 교차 네트워크 개체를 마치 로컬 개체 인 것처럼 사용합니다. Decorator는 원래 인터페이스에 새로운 동작을 추가하기위한 것입니다.

두 패턴의 구조는 비슷하지만 Proxy의 복잡성은 소스 개체와의 적절한 통신을 보장하는 데 있습니다. 반면 데코레이터는 추가 된 동작의 구현에 중점을 둡니다.


이미 다른 4 가지 답변과 다른 점을 말하고 있습니까?
Stephen Rauch

모든 것이 있는지 모르겠습니다. 나는 단지 이전의 답변을 읽은 후에 차임하려는 충동을 느꼈습니다.
James Lin

1

답변과 그 의미 를 파악하는 데 시간 걸렸습니다 . 몇 가지 예가 더 명확해야합니다.

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, 꽤 바보 같은 사람이 있습니다 :

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

지금까지 특이한 것은 없습니까? 특정 서비스에서 토큰을 얻으려면 해당 토큰을 사용하십시오. 이제 그림에 요구 사항이 하나 더 있습니다. 로깅을 추가하십시오. 매번 토큰을 기록한다는 의미입니다. 이 경우 간단합니다 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 보유 의 인스턴스를 DBAuthorization. 두 LoggingDBAuthorizationDBAuthorization 구현 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;
    } 
}

공지 사항 내가 말한 어떻게 플러스 다른 구직자의 하나 , 하지 Newbie . A Decorator는 그것이 무엇을 꾸미고 있는지 정확히 알지 못하고 , 장식 된 인스턴스의 계약 만 알고 있습니다 (에 대해 아는 것 JobSeeker). 여기서는 이와 다릅니다 Proxy. 대조적으로, 그것이 무엇을 장식하는지 정확히 알고 있습니다.

이 경우 두 디자인 패턴간에 실제로 차이가 있는지 의문을 가질 수 있습니까? 어떻게 우리가 작성하려고하면 DecoratorA와를 Proxy?

public class TwoYearsInTheIndustry implements JobSeeker {

    private final Newbie newbie = new Newbie();

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

이것은 확실히 옵션이며 이러한 패턴이 얼마나 가까운 지 강조합니다. 그들은 여전히 ​​다른 답변에서 설명 된 것처럼 다른 시나리오를위한 것입니다.


1

프록시 는 래핑 된 객체에 동일한 인터페이스를 제공하고, Decorator 는 향상된 인터페이스를 제공하며, 프록시는 일반적으로 서비스 객체의 수명주기를 자체적으로 관리하지만 데코레이터의 구성은 항상 클라이언트에 의해 제어됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.