ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [C++] 특정 클래스만 함수를 호출할 수 있게 하는 방법 - Attorney and Client Idiom, Passkey Pattern
    쾌락없는 책임 (공부)/C++ 짜잘이 2023. 10. 22. 15:19
    반응형

    서론

    그냥 갑자기 문득 '입력을 한곳에서 받은 뒤 다른 곳에서는 읽기만 할 수 있게 못할까?'라는 생각이 들었습니다. 유니티에서 `Input.~~`로 표현해 사용하는걸 자체적으로 만들 수 없을까 하는 생각이었습니다.

     

    여기서 드는 생각이 '그러면 입력을 받아주는 곳은 한곳이고 나머지는 전부 읽기 전용이어야 한다'입니다. 그러면 **어떻게 특정 클래스에게만 이런 권한을 줄 수 있냐**하는 의문이죠. 결국 이 의문이 커져서 이번에 소개할 `Attorney and Client idiom`과 `Passkey Pattern`을 보게 되었습니다.

     

    Attorney and Client idiom

    일단 이 방식은 간단합니다. C++에서 제공하는 `friend` 키워드를 사용하는 것입니다.

    class Some
    {
    private :
        void WriteA() {}
        void WriteB() {}
    
    friend class SomeAttroney;
    };
    
    class Attorney
    {
    public:
        void CallSomeWriteA(Some* SomePtr)
        {
        	SomePtr->WriteA();
        }
    
    friend class SomeClient;
    };
    
    class SomeClient
    {
    // 이곳에서 Attorney를 통해 함수를 호출하면 됩니다
    // Attorney에서 제공해주는 Some의 함수들을 사용할 수 있습니다.
    };

     

    `Some`과 `SomeClient` 사이 바로 friend를 선언하게 되면 Some의 모든 private 함수에 접근이 가능하게 되므로 중간에 `Attorney`를 둬서 Attorney가 제공할 함수들을 선정하고 이 Attorney를 통해서 함수를 사용하는 것입니다.

     

    간단하고 복잡하지 않은 구조라 이해가 쉽다는 장점이 있는 구조입니다. 다만 `friend`라는 만능 키워드를 사용하게 되기에 모든 캡슐화와 객체지향적인 설계가 무너지게 되며 클라이언트가 늘어날 때마다 friend를 계속해서 선언해줘야 한다는 단점이 있는 패턴입니다.

     

    실제로는 잘 보지 못하게 될 패턴으로 생각됩니다. 제가 할 일도 없어 보이구요.

     

    Passkey Pattern

    이전과는 다르게 템플릿을 사용하는 패턴입니다.

     

    template<typename T>
    class Key
    {
        friend T;
        Key() = default; // 생성자가 private
    };

     

    이런 템플릿 클래스가 이제 키가 되는 것입니다.

     

    class Client;
    
    class Actor
    {
    public:
        Vector GetActorLocation(Key<Client>)
        {
        	return Location;
        }
    };
    
    class Clinet
    {
    public:
        void CalculateByActorLoaction(const Actor* SomeActor)
        {
            //...
            SomeActor->GetActorLocation({});
        }
    }

     

    위에서 Actor 클래스는 GetActorLocation에서 `Key<Client>`를 인자로 받고 있습니다. 이로 인해서 Clinet만 접근 권한을 가지게 되는 것이죠.

    • 외부에서 부를 수 없는 이유는 T 만이 friend 클래스가 되기 때문

    이로 인해 Client 클래스 안에서만 저 함수를 호출할 수 있는 권한이 주어진 것입니다. 그리고 인자로 `{}`를 준 이유는 저렇게만 해도 컴파일러가 알아서 `Key<Camera>`를 넣어준다고 합니다.

    반응형

    댓글

Designed by Tistory.