2009-06-15 5 views
31

C++에서 프록시 클래스 란 무엇입니까? 왜 그것이 만들어지고 어디에 유용합니까?C++에서 프록시 클래스 란 무엇입니까?

+1

프록시 (많은 다른 의미 중) 인 디자인 패턴 ** ** 비주얼 스튜디오 콘솔 애플리케이션으로부터 본 실시 예의 출력 ] (http://en.wikipedia.org/wiki/Proxy_pattern)을 참조하십시오 (강하게 C++이 아닌 것은 물론입니다). –

+0

이 완전히 동의합니다.이 질문에 대한 답은 우수합니다. – vsoftco

답변

58

프록시는 다른 클래스에 수정 된 인터페이스를 제공하는 클래스입니다.

struct array1 { 
    int mArray[10]; 
    int & operator[](int i) { 
     /// what to put here 
    } 
}; ` 

우리는 우리가 말할 경우 연산자 [] 불평 할 : - 다음 예는 우리가 단지 1 또는 여기에 0이 첫 번째 시도 인 이진수를 포함 할 수 있도록하려는 배열 클래스가 있다고 가정 a [1] = 42와 같은 것입니다. 그러나 연산자는 배열의 인덱스가 저장되는 값이 아니라보기 만하기 때문에 가능하지 않습니다.

우리는이 사용하여 프록시를 해결할 수 :

#include <iostream> 
using namespace std; 

struct aproxy { 
    aproxy(int& r) : mPtr(&r) {} 
    void operator = (int n) { 
     if (n > 1) { 
      throw "not binary digit"; 
     } 
     *mPtr = n; 
    } 
    int * mPtr; 
}; 

struct array { 
    int mArray[10]; 
    aproxy operator[](int i) { 
     return aproxy(mArray[i]); 
    } 
}; 

int main() { 
    try { 
     array a; 
     a[0] = 1; // ok 
     a[0] = 42; // throws exception 
    } 
    catch (const char * e) { 
     cout << e << endl; 
    } 
} 

프록시 클래스는 지금 이진수에 대한 우리의 검사를 수행하고 우리가 배열의 연산자 []를 제한 액세스 할 수있는 프록시의 인스턴스를 반환 할 배열 내부.

+1

'aproxy :: void operator = (int n)'을'int'로 반환하면'a [0] ] = a [1] = 0'이다. 그렇지 않으면'a [1] = 0'에 의해 반환되는'aproxy'를'a [0]'에 복사하고 예상대로 작동하고 있습니다. 그 외에도 위대하고 간결한 대답! – vsoftco

2

프록시 클래스을 사용하면 클래스의 클라이언트 개인 클래스의 데이터를 숨길 수 있습니다.

클래스에 대한 공용 인터페이스 만 알고있는 프록시 클래스를 클라이언트에 제공하면 클라이언트가 클래스의 구현 세부 사항에 대한 클라이언트 액세스 권한을 부여하지 않고도 클래스의 서비스를 사용할 수 있습니다.

8

C++의 프록시 클래스는 객체가 다른 객체의 인터페이스 또는 조정자 인 Proxy Pattern을 구현하는 데 사용됩니다.

C++에서 프록시 클래스의 일반적인 사용은 [] 연산자를 사용하여 데이터를 가져 오거나 객체 내에서 데이터를 설정하기 때문에 [] 연산자를 구현합니다. 개념은 [] 연산자의 데이터 사용량 대 [] 연산자의 데이터 사용량을 감지 할 수있는 프록시 클래스를 제공하는 것입니다. 클래스의 [] 연산자는 프록시 객체를 사용하여 [] 연산자가 객체의 데이터를 가져 오거나 설정하는 데 사용되는지 여부를 감지하여 올바른 작업 수행을 지원합니다.

C++ 컴파일러는 제공된 연산자와 변환 연산자를 제공된 대상 클래스와 프록시 클래스 정의에서 선택하여 [] 연산자를 사용합니다.

그러나 C++의 프록시 클래스에는 다른 용도가 있습니다. 예를 들어 Dr. Dobbs의 Self-Registering Objects in C++에 대한이 기사에서는 프록시 클래스를 객체 팩토리의 일부로 사용하는 방법에 대해 설명합니다. 객체 팩토리는 일부 기준 (이 예에서는 그래픽 이미지 형식)에 따라 특정 유형의 객체를 제공합니다. 상이한 그래픽 이미지 변환기 각각은 프록시 객체로 표현된다.

이러한 요구 사항의 모든

는 지원되는 모든 형식에 대한 을 알고 컴파일시 코드에는 한 곳도 없다 에서 "전문점"을 사용하여 충족시킬 수있다. 지원되는 개체 목록은 각 파일 형식 개체가 특수 저장소 개체로 해당 개체를 등록 할 때 런타임 인 ​​ 에 작성됩니다.

  • 가게에가는 각 클래스는 프록시 클래스에 의해 표현됩니다 전문점을 구축하는 네 부분으로는

    있다.프록시는 상점의 오브젝트를 작성하는 f}을 알고 있으며 은 클래스에 대한 정보에 대한 표준 인터페이스를 제공합니다.

  • 전문점에서 호출자에게 공개 할 기준을 결정한 다음 저장소에 해당 기준의 인터페이스를 구현하고 프록시 클래스 및 원래 클래스에 인터페이스를 구현해야합니다.
  • 모든 프록시 클래스는 공통 기본 클래스에서 파생되므로 전문 상점에서는이를 서로 사용할 수 있습니다. 각 프록시 클래스는 원래 클래스의 정적 함수를 호출하는 템플릿으로 구현 된 입니다.
  • 프록시 클래스는 생성자 이 전문 저장소에 프록시 클래스를 등록 할 각 프록시 클래스에 대한 전역 변수를 정의하여 프로그램 시작시 자동으로 등록됩니다. 마이크로 소프트 DCOM (분산 COM) 개체를 다른 호스트 시스템에있는 실제 객체를 표현하기 위해 DCOM 객체의 사용자의 호스트 시스템에 프록시를 사용하는 방법

또 다른 예는 것입니다. 프록시는 다른 시스템의 실제 오브젝트에 대한 인터페이스를 제공하고 오브젝트의 사용자와 실제 오브젝트 간의 통신을 처리합니다.

요약하면 프록시 개체는 실제 개체에 대한 매개 역할을하는 데 사용됩니다. 프록시 객체는 객체의 사용자와 실제 객체 간의 일종의 변환이나 변형이 필요할 때 사용됩니다. 실제 객체를 사용하는 데 장애가있을 때 실제 객체를 사용할 수있는 서비스를 제공하는 일종의 간접 지정이 있습니다. 실제 개체를 직접.

EDIT - 간단한 배열 데이터 저장소

다음 소스 [] 연산자 프록시를 사용하는 간단한 예는 클래스의 연산자 []에 프록시 객체를 사용한다. 테스트 클래스의 출력은 프록시 클래스가 실제 클래스에 액세스하고 조작하는 데 사용되므로 다양한 프록시 객체의 생성 및 제거를 보여주기 위해 아래에 제공됩니다. 디버거에서 실행하여 실행하는 것을 지켜 보는 것이 좋습니다. 참조 [위키 -

// proxy.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include <string.h> 

#include <iostream> 

class TArrayProxy; 

// The actual class which we will access using a proxy. 
class TArray 
{ 
public: 
    TArray(); 
    ~TArray(); 

    TArrayProxy operator [] (int iIndex); 
    int operator = (TArrayProxy &j); 
    void Dump (void); 

    char m_TarrayName[4];  // this is the unique name of a particular object. 

    static char TarrayName[4]; // This is the global used to create unique object names 

private: 
    friend class TArrayProxy; // allow the proxy class access to our data. 
    int iArray[10];    // a simple integer array for our data store 
}; 

// The proxy class which is used to access the actual class. 
class TArrayProxy 
{ 
public: 
    TArrayProxy(TArray *p = 0, int i=0); 
    ~TArrayProxy(); 

    TArrayProxy & operator = (int i); 
    TArrayProxy & operator += (int i); 
    TArrayProxy & operator = (TArrayProxy &src); 
    operator int(); 

    int  iIndex; 
    char m_TarrayproxyName[4];  // this is the unique name of a particular object. 

    static char TarrayproxyName[4];  // This is the global used to create unique object names 

private: 
    TArray *pArray;      // pointer to the actual object for which we are a proxy. 
}; 

// initialize the object names so as to generate unique object names. 
char TArray::TarrayName[4] = {" AA"}; 
char TArrayProxy::TarrayproxyName[4] = {" PA"}; 

// Construct a proxy object for the actual object along with which particular 
// element of the actual object data store that this proxy will represent. 
TArrayProxy::TArrayProxy(TArray *p /* = 0 */, int i /* = 0 */) 
{ 
    if (p && i > 0) { 
     pArray = p; 
     iIndex = i; 
     strcpy (m_TarrayproxyName, TarrayproxyName); 
     TarrayproxyName[2]++; 
     std::cout << " Create TArrayProxy " << m_TarrayproxyName << " iIndex = " << iIndex << std::endl; 
    } else { 
     throw "TArrayProxy bad p"; 
    } 
} 

// The destructor is here just so that we can log when it is hit. 
TArrayProxy::~TArrayProxy() 
{ 
    std::cout << "  Destroy TArrayProxy " << m_TarrayproxyName << std::endl; 
} 

// assign an integer value to a data store element by using the proxy object 
// for the particular element of the data store. 
TArrayProxy & TArrayProxy::operator = (int i) 
{ 
    pArray->iArray[iIndex] = i; 
    std::cout << "  TArrayProxy assign = i " << i << " to " << pArray->m_TarrayName << " using proxy " << m_TarrayproxyName << " iIndex " << iIndex << std::endl; 
    return *this; 
} 

TArrayProxy & TArrayProxy::operator += (int i) 
{ 
    pArray->iArray[iIndex] += i; 
    std::cout << "  TArrayProxy add assign += i " << i << " to " << pArray->m_TarrayName << " using proxy " << m_TarrayproxyName << " iIndex " << iIndex << std::endl; 
    return *this; 
} 

// assign an integer value that is specified by a proxy object to a proxy object for a different element. 
TArrayProxy & TArrayProxy::operator = (TArrayProxy &src) 
{ 
    pArray->iArray[iIndex] = src.pArray->iArray[src.iIndex]; 
    std::cout << "  TArrayProxy assign = src " << src.m_TarrayproxyName << " iIndex " << src.iIndex << " to " << m_TarrayproxyName << " iIndex "<< iIndex << " from" << std::endl; 
    return *this; 
} 

TArrayProxy::operator int() 
{ 
    std::cout << "  TArrayProxy operator int " << m_TarrayproxyName << " iIndex " << iIndex << " value of " << pArray->iArray[iIndex] << std::endl; 
    return pArray->iArray[iIndex]; 
} 



TArray::TArray() 
{ 
    strcpy (m_TarrayName, TarrayName); 
    TarrayName[2]++; 
    std::cout << " Create TArray = " << m_TarrayName << std::endl; 
    for (int i = 0; i < sizeof(iArray)/sizeof(iArray[0]); i++) { iArray[i] = i; } 
} 

// The destructor is here just so that we can log when it is hit. 
TArray::~TArray() 
{ 
    std::cout << " Destroy TArray " << m_TarrayName << std::endl; 
} 

TArrayProxy TArray::operator [] (int iIndex) 
{ 
    std::cout << " TArray operator [" << iIndex << "] " << m_TarrayName << std::endl; 
    if (iIndex > 0 && iIndex <= sizeof(iArray)/sizeof(iArray[0])) { 
     // create a proxy object for this particular data store element 
     return TArrayProxy(this, iIndex); 
    } 
    else 
     throw "Out of range"; 
} 

int TArray::operator = (TArrayProxy &j) 
{ 
    std::cout << " TArray operator = " << m_TarrayName << " from" << j.m_TarrayproxyName << " index " << j.iIndex << std::endl; 
    return j.iIndex; 
} 

void TArray::Dump (void) 
{ 
    std::cout << std::endl << "Dump of " << m_TarrayName << std::endl; 
    for (int i = 0; i < sizeof(iArray)/sizeof(iArray[0]); i++) { 
     std::cout << " i = " << i << " value = " << iArray [i] << std::endl; 
    } 
} 

// ----------------- Main test harness follows ---------------- 
// we will output the line of code being hit followed by the log of object actions. 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    TArray myObj; 

    std::cout << std::endl << "int ik = myObj[3];" << std::endl; 
    int ik = myObj[3]; 
    std::cout << std::endl << "myObj[6] = myObj[4] = 40;" << std::endl; 
    myObj[6] = myObj[4] = 40; 
    std::cout << std::endl << "myObj[5] = myObj[5];" << std::endl; 
    myObj[5] = myObj[5]; 
    std::cout << std::endl << "myObj[2] = 32;" << std::endl; 
    myObj[2] = 32; 
    std::cout << std::endl << "myObj[8] += 20;" << std::endl; 
    myObj[8] += 20; 
    myObj.Dump(); 
    return 0; 
} 

그리고 여기 2005

Create TArray = AA 

int ik = myObj[3]; 
    TArray operator [3] AA 
    Create TArrayProxy PA iIndex = 3 
     TArrayProxy operator int PA iIndex 3 value of 3 
     Destroy TArrayProxy PA 

myObj[6] = myObj[4] = 40; 
    TArray operator [4] AA 
    Create TArrayProxy PB iIndex = 4 
     TArrayProxy assign = i 40 to AA using proxy PB iIndex 4 
    TArray operator [6] AA 
    Create TArrayProxy PC iIndex = 6 
     TArrayProxy assign = src PB iIndex 4 to PC iIndex 6 from 
     Destroy TArrayProxy PC 
     Destroy TArrayProxy PB 

myObj[5] = myObj[5]; 
    TArray operator [5] AA 
    Create TArrayProxy PD iIndex = 5 
     TArrayProxy operator int PD iIndex 5 value of 5 
    TArray operator [5] AA 
    Create TArrayProxy PE iIndex = 5 
     TArrayProxy assign = i 5 to AA using proxy PE iIndex 5 
     Destroy TArrayProxy PE 
     Destroy TArrayProxy PD 

myObj[2] = 32; 
    TArray operator [2] AA 
    Create TArrayProxy PF iIndex = 2 
     TArrayProxy assign = i 32 to AA using proxy PF iIndex 2 
     Destroy TArrayProxy PF 

myObj[8] += 20; 
    TArray operator [8] AA 
    Create TArrayProxy PG iIndex = 8 
     TArrayProxy add assign += i 20 to AA using proxy PG iIndex 8 
     Destroy TArrayProxy PG 

Dump of AA 
    i = 0 value = 0 
    i = 1 value = 1 
    i = 2 value = 32 
    i = 3 value = 3 
    i = 4 value = 40 
    i = 5 value = 5 
    i = 6 value = 40 
    i = 7 value = 7 
    i = 8 value = 28 
    i = 9 value = 9 
관련 문제