프록시 와 데코레이터 의 차이점은 무엇 입니까?
내가 볼 수있는 주요 차이점은 프록시 가 컴포지션을 사용 하고 데코레이터 가 집계 를 사용 한다고 가정 할 때 여러 (하나 이상의) 데코레이터 를 사용하여 기존 인스턴스 (장식)에 기능을 수정 / 추가 할 수 있다는 것이 분명해 보입니다. 프록시 는 프록시 클래스의 내부 인스턴스를 가지고 있으며 추가 기능 (프록시 동작)을 추가하여 위임합니다.
문제는 -합니까 프록시는 집계가 아직 만들어 프록시 또는 오히려 실내 장식 ? GoF 패턴으로 정의 하여 집계 를 사용하여 프록시 를 만들 수 있습니까?
답변
다음은 GoF에서 직접 인용 한 것입니다 (216 페이지).
데코레이터는 프록시와 유사한 구현을 가질 수 있지만 데코레이터는 다른 목적을 가지고 있습니다. 데코레이터는 객체에 하나 이상의 책임을 추가하는 반면 프록시는 객체에 대한 액세스를 제어합니다.
프록시는 데코레이터처럼 구현되는 정도가 다릅니다. 보호 프록시는 데코레이터와 똑같이 구현 될 수 있습니다. 반면에 원격 프록시에는 실제 주제에 대한 직접 참조가 아니라 “호스트 ID 및 호스트의 로컬 주소”와 같은 간접 참조 만 포함됩니다. 가상 프록시는 파일 이름과 같은 간접 참조로 시작하지만 결국 직접 참조를 가져 와서 사용합니다.
인기있는 답변은 대리인이 구체적인 유형의 대리인을 알고 있음을 나타냅니다. 이 인용문에서 우리는 항상 사실이 아니라는 것을 알 수 있습니다.
GoF에 따른 프록시와 데코레이터의 차이점은 프록시 가 클라이언트를 제한 한다는 것입니다. 데코레이터는하지 않습니다. 프록시 클라이언트가 무엇을 제한 할 수 있습니다 않는 기능에 대한 액세스를 제어하여, 또는 고객이 알고있는 것을 제한 할 수 있습니다 보이지 않고 알려지지 않은 작업을 수행 . Decorator는 그 반대입니다. 대리자가 클라이언트가 볼 수있는 방식으로 업무를 향상시킵니다.
우리는 프록시가 블랙 박스이고 데코레이터가 화이트 박스라고 말할 수 있습니다.
래퍼와 델리게이트 간의 컴포지션 관계는 Proxy와 Decorator를 대조 할 때 중점을 두는 잘못된 관계입니다. 컴포지션은이 두 패턴이 공통적으로 갖는 기능이기 때문입니다. 랩퍼와 클라이언트의 관계는이 두 패턴을 차별화하는 것입니다.
- Decorator는 고객에게 정보를 제공하고 권한을 부여합니다.
- 프록시는 클라이언트를 제한하고 해제합니다.
답변
실제 차이점은 소유권 (구성 대 집계)이 아니라 형식 정보입니다.
실내 장식이 되어 항상 그 위임자을 통과시켰다. 프록시 수 그것을 자신을 만들거나 그 수 는 주사 있습니다.
그러나 대리인은 항상 특정 유형의 대리인을 알고 있습니다. 다시 말해, 프록시 와 대리인은 동일한 기본 유형을 가지지 만 프록시는 파생 된 유형을 가리 킵니다. 실내 장식 자신의 기본 유형을 가리키는. 따라서 델리게이트 유형에 대한 컴파일 타임 정보가 다릅니다.
동적 언어에서 대의원이 주입되어 동일한 인터페이스를 갖는 경우 아무런 차이가 없습니다.
귀하의 질문에 대한 답변은 “예”입니다.
답변
데코레이터 패턴은 객체에 기능을 동적으로 추가하는 데 중점을 두며 프록시 패턴은 객체에 대한 액세스를 제어하는 데 중점을 둡니다.
편집하다:-
프록시 와 실제 주제 간의 관계 는 일반적으로 컴파일 타임에 설정되고 프록시 는 어떤 방식으로 인스턴스화하는 반면 데코레이터 는 런타임에 주제의 인터페이스 만 알고 주제에 할당됩니다.
답변
데코레이터 는 장식 된 객체 (일반적으로 생성자를 통해)에 대한 참조를 가져 오지만 프록시 는 직접 그 역할을 담당합니다.
데코레이터가 항상 실제 랩핑 된 인스턴스에 대한 링크를 보유 하는 동안 프록시 는 랩핑 오브젝트를 전혀 인스턴스화하지 않을 수 있습니다 (오브젝트 필드 / 게터가 사용되지 않는 경우 DB에 대한 불필요한 액세스를 방지하기 위해 ORM을 수행함) .
프록시는 일반적으로 프레임 워크에서 보안 또는 캐싱 / 레이 징을 추가하고 프레임 워크별로 구성합니다 (일반 개발자가 아닌).
데코레이터는 일반적으로 실제 클래스가 아닌 인터페이스를 기반으로 개발자가 기존 클래스 또는 레거시 클래스에 새로운 동작을 추가하는 데 사용되었습니다 (따라서 광범위한 인터페이스 인스턴스에서 작동하며 프록시 는 콘크리트 클래스를 중심으로합니다).
답변
주요 차이점 :
- 프록시 는 동일한 인터페이스를 제공합니다. Decorator 는 향상된 인터페이스를 제공합니다.
- 데코레이터 와 프록시 는 목적이 다르지만 구조는 비슷합니다. 둘 다 다른 객체에 대한 간접적 인 수준을 제공하는 방법을 설명하고 구현은 요청을 전달하는 객체에 대한 참조를 유지합니다.
- 데코레이터 는 하나의 구성 요소 만있는 축퇴 합성물로 볼 수 있습니다. 그러나 데코레이터는 추가 책임을 추가합니다. . 객체 집계를위한 것이 아닙니다.
- 데코레이터 는 재귀 구성을 지원합니다
- 데코레이터 클래스는 선언 조성 액정 (최저 등급 분모) 인터페이스에 관계하고,이 데이터가 부재 생성자에서 초기화된다.
- 개체를 캐싱 하고 클라이언트 / 호출자에 대한 액세스를 제어 하여 지연 초기화, 성능 향상을 위해 프록시 사용
소스 메이킹 기사는 유사점과 차이점을 훌륭한 방법으로 인용합니다.
관련 SE 질문 / 링크 :
답변
프록시와 데코레이터는 목적과 내부 구현에 중점을 둔 부분이 다릅니다. 프록시는 원격, 교차 프로세스 또는 교차 네트워크 개체를 마치 로컬 개체 인 것처럼 사용합니다. Decorator는 원래 인터페이스에 새로운 동작을 추가하기위한 것입니다.
두 패턴의 구조는 비슷하지만 Proxy의 복잡성은 소스 개체와의 적절한 통신을 보장하는 데 있습니다. 반면 데코레이터는 추가 된 동작의 구현에 중점을 둡니다.
답변
이 답변과 그 의미 를 파악하는 데 시간 이 걸렸습니다 . 몇 가지 예가 더 명확해야합니다.
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
. 두 LoggingDBAuthorization
및 DBAuthorization
구현 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
. 대조적으로, 그것이 무엇을 장식하는지 정확히 알고 있습니다.
이 경우 두 디자인 패턴간에 실제로 차이가 있는지 의문을 가질 수 있습니까? 어떻게 우리가 작성하려고하면 Decorator
A와를 Proxy
?
public class TwoYearsInTheIndustry implements JobSeeker {
private final Newbie newbie = new Newbie();
@Override
public int interviewScore() {
return newbie.interviewScore() + 20;
}
}
이것은 확실히 옵션이며 이러한 패턴이 얼마나 가까운 지 강조합니다. 그들은 여전히 다른 답변에서 설명 된 것처럼 다른 시나리오를위한 것입니다.