Exist Technote

[Python] Registry Pattern (레지스트리 패턴) 본문

Design Pattern/Behavioral

[Python] Registry Pattern (레지스트리 패턴)

by_Exist 2020. 10. 15. 02:26

너는 A 클래스를 상속하여 만들어졌구나!

Registry Pattern이란?

  • 어떤 클래스의 모든 서브 클래스를 참조하고 싶을 때 사용할 수 있는 패턴

예제

# 메타클래스 정의(클래스를 생성하는 클래스)
class RegistryMetaClass(type):

    def __new__(cls, name, bases, attrs):
        # 클래스를 생성한다.
        new_cls = type.__new__(cls, name, bases, attrs)
        # 클래스의 속성에 REGISTRY가 있다면 
        # bases 내에 RegistryMetaClass를 메타 클래스로 활용한 슈퍼 클래스가 있다는 의미로 간주하여
        if hasattr(new_cls, "REGISTRY"):
            # (다중 상속에도 원하는 방식으로 동작하도록)
            for base in bases:
                if hasattr(base, "REGISTRY"):
                    # REGISTRY에 생성된 클래스를 등록한다.
                    base.REGISTRY[name] = new_cls
        # REGISTRY 속성이 없다면
        else:
            # RegistryMetaClass가 메타 클래스로 활용되었으므로 REGISTRY 속성을 부여한다.
            new_cls.REGISTRY = {}
        return new_cls

# REGISTRY를 지닐 첫번째 클래스
class BaseRegClassOne(metaclass=RegistryMetaClass):
    pass

# REGISTRY를 지닐 두번째 클래스
class BaseRegClassTwo(metaclass=RegistryMetaClass):
    pass

if __name__ == "__main__":

    # BaseRegClassOne 또는 BaseRegClassTwo를 상속하는 클래스가 없는 상태.
    print(BaseRegClassOne.REGISTRY)
    print(BaseRegClassTwo.REGISTRY)

    class JoinClassOne(BaseRegClassOne):
        pass

    class JoinClassTwo(BaseRegClassTwo):
        pass

    # 서브 클래싱 시 자동으로 슈퍼 클래스의 REGISTRY에 등록
    print(BaseRegClassOne.REGISTRY)
    print(BaseRegClassTwo.REGISTRY)

    # 다중 상속 관계에서도 원하는 방식으로 동작한다.
    class TestClass(BaseRegClassOne, BaseRegClassTwo):
        pass

    print(BaseRegClassOne.REGISTRY)
    print(BaseRegClassTwo.REGISTRY)

여담

  • 모든 서브클래스에 대한 옵저버 패턴에서 사용될 수 있으려나? 사용성이 있는 패턴인지 모르겠다.
  • 메타 클래스를 깊게 이해한 상태가 아닌지라 커스텀 코드가 안전한지, 가장 효율적인 방식인지 등등 확신이 서지 않는다.
  • REGISTRY라는 속성을 클라이언트가 알아서 사용하기 보다는 registry 프로퍼티를 부여하는 편이 좋지 않을까?
Comments