본문 바로가기
Python/Python 개념

파이썬 디자인 패턴 - 1

by hyun-am 2020. 12. 9.

디자인 패턴 개념

 

디자인 패턴이란 잘 설계된 구조의 형식적 정의를 소프트웨어 엔지니어링으로 옮긴 것입니다. 다양한 디자인 패턴이 있고 이들을 사용하여 서로 다른 문제를 해결할 수 있습니다.

 

먼저 패턴종류로는 생성패턴, 구조패턴, 행위패턴이 있습니다.

여기서 패턴속에 있는 항목중에 대표적인 패턴으로 예시를 들겠습니다. 생성패턴에서는 싱글톤패턴, 구조패턴에서는 데코레이터 패턴, 마지막으로 행위 패턴에서는 옵저버 패턴을 참고하겠습니다.

 

싱글톤 패턴(singleton)

 

초기화된 객체의 인스턴스를 전역에서 사용하는 패턴을 싱글턴 패턴이라고 합니다. 이 객체의 인스턴스는 하나만 존재합니다. 자바에서 singleton특징은 private constructorstatic method를 사용한다는 점입니다. 하지만 파이썬에는 private와 같은 접근자가 없기 때문에

__new__()

클래스 메서드를 가지고 하나의 인스턴스만 생성되도록 구현해야 합니다.

 

싱글톤 예제

먼저 싱글턴은 인스턴스가 하나만 있어야 하므로 만약에 이미 싱글턴 인스턴스가 생성 되어있는지 확인합니다. 만약에 싱글턴 메서드가 없으면 슈퍼클래스를 호출하여 싱글턴 인스턴스를 만들어 주겠습니다.

이제 만약에 싱글턴 인스턴스가 없을때와 싱글턴 인스턴스가 존재할때 한번 확인하겠습니다.

 

class Singleton:
    _sing = None

    def __new__(self, *args, **kwargs):
        if not self._sing:
            self._sing = super(Singleton, self).__new__(self, *args, **kwargs)

        return self._sing


x = Singleton()
print(x)
y = Singleton()
print(y)

## 출력값
# <__main__.Singleton object at 0x7f8d68135c70>
# <__main__.Singleton object at 0x7f8d68135c70>

다음과 같이 두 객체의 주소가 같은것을 확인할 수 있습니다.

 

다음은 구조패턴 중 하나인 데코레이터 패턴을 확인하겠습니다.

데코레이터(decorator)

 

파이썬에서 데코레이터 패턴은 @표기를 통해 함수 또는 메서드의 변환을 우아하게 지정해줄 수 있는 도구입니다.

데코레이터 패턴은 함수의 객체와 함수를 변경하는 다른 객체의 랩핑을 허용해 줍니다.

먼저 기본적인 사용 에시는 다음과 같습니다.

class MainClass(object):
    @my_decorator
    def method(self):
        # 메서드 내용

이코드를 해석하자면 아래 코드와 같습니다.

class MainClass(object):
    def method(self):
        # 메서드 내용
    method = my_decorator(method)

 

다음은 파이썬에서 일반적으로 사용하는 데코레이터인 @classmethod와 @static-method를 보겠습니다.

@classmethod는 첫 번째 인수로 클래스(cls)를 사용하고, @staticmethod는 첫번째 인수로 self 또는 cls가 없습니다. 클래스 내 변수에 접근하려면 @classmethod의 첫 번째 인수를 사용할 수 있습니다.

예시 코드는 다음과 같습니다.

class A(object):
    _hello = True

    def foo(self, x):
        print(f"foo({self},{x}) 실행")

    @classmethod
    def class_foo(cls, x):
        print(f"class_foo({cls},{x})실행 : {cls._hello}")

    @staticmethod
    def static_foo(x):
        print(f"static_foo({x}) 실행")


if __name__ == "__main__":
    a = A()
    a.foo(1)
    a.class_foo(2)
    A.class_foo(2)
    a.static_foo(3)
    A.static_foo(3)

## 출력 값
# foo(<__main__.A object at 0x7ffe9c12bf70>,1) 실행
# class_foo(<class '__main__.A'>,2)실행 : True
# class_foo(<class '__main__.A'>,2)실행 : True
# static_foo(3) 실행
# static_foo(3) 실행

 

다른 내용의 데코레이터 패턴은 아래 주소를 참고해 주시길 바랍니다.

https://hyun-am-coding.tistory.com/entry/파이썬-데코레이터?category=778330

 

마지막으로 행위 패턴 중 하나인 옵저버 패턴을 설명하겠습니다.

 

옵저버 패턴(Observer)

옵저버 패턴이란 특정 값을 유지하는 핵심 객체를 갖고, 직렬화된 객체의 복사본을 생성하는 일부 옵저버가 있는 경우 유용합니다. 즉, 객체의 일대다(one to many) 의존 관계에서 한 객체의 상태가 변경되면, 그 객체에 종속된 모든 객체에 그 내용을 통지하여 자동으로 상태를 갱신하는 방식입니다.

옵저버 패턴을 구현하려면 @property 데커레이터를 이용하면 쉽게 구현할 수 있습니다. 예를 들면 속성을 읽기 전용으로 설정하는 것과 같은 속성 접근을 제어할 수 있습니다. 속성은 접근자나 getter/setter 메서드 대신 사용하면 되겠습니다. 간단한 예시는 다음과 같습니다.

 

class Data:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, new_name):
        self._name = f"{self._name} >> {new_name}"


person_a = Data("박길동")

print(person_a.name)

person_a.name = "김길동"
print(person_a.name)

# 출력 값
# 박길동
# 박길동 >> 김길동

 

 

참고 서적

 

파이썬 자료구조와 알고리즘 : https://books.google.co.kr/books/about/파이썬_자료구조와_알고리즘.html?id=L12nDwAAQBAJ&printsec=frontcover&source=kp_read_button&redir_esc=y#v=onepage&q&f=false

 

댓글