디자인 패턴은 언어에 독립적이라고는 하나 같은 기능이라도 언어에 따라 구현의 난이도가 다를 수 있기 때문에 디자인 패턴에도 영향을 받는다. 실제로 동적 프로그래밍 언어에서는 <GoF의 디자인패턴> 책에서 정의한 23가지 패턴 중 16가지 패턴이 잘 보이지 않거나 단순해진다는 말이 있다. 파이썬의 일급 함수 기능을 이용해 다른 언어에서의 디자인 패턴을 리팩토링하여 단순화해보자.
중요 키워드
전략 패턴, globals, inspect.getmembers, inspect.isfunction
명령 패턴
덜 중요한 키워드
abc.ABC abc.abstractmethod
참고 자료
http://bit.ly/1HGC0r5
전략 패턴(strategy pattern)은 일련의 명령 중 일부만 다른 클래스에 위임함으로써 유연하게 처리할 수 있게 하는 패턴이다. 일련의 명령을 실행하는 클래스를 컨텍스트 클래스, 위임되는 일부 명령을 수행하는 클래스를 전략 클래스라 한다. 전략 클래스는 하나의 추상 베이스 클래스와 이를 상속하는 구체화된 여러 하위 클래스로 구성된다. 컨텍스트 클래스는 구체화된 전략 클래스의 메서드를 통해 명령을 일부만 위임할 수 있고 컨텍스트 클래스에 어떤 전략 클래스를 넘겨주냐에 따라 결과가 달라지는 유연한 구조를 만들 수 있다.
이때 파이썬에서 추상 베이스 클래스를 만들기 위해서는 abc.ABC를 상속하도록 하고 하나 이상의 메서드에 abc.abstractmethod를 데코레이터로 지정해야 한다.
하지만 파이썬은 함수가 일급객체이기 때문에 메서드가 하나인 인터페이스는 함수로 정의하여 전달하여 간단하게 할 수 있다.
모든 구체화된 전략 클래스의 리스트를 얻으려면 부모 클래스.__subclass__
함수를 이용한다. 하지만 파이썬의 일급함수 성질을 이용해서 함수로 바꾼 경우 전략 함수의 리스트를 얻으려면 다음 2가지 방법 중 하나를 이용한다.
globals
함수를 통해 모든 변수, 함수, 모듈, 클래스 이름과 객체가 key-value쌍으로 된 dict를 불러올 수 있다. key를 통해 네이밍 규칙을 두어 원하는 함수를 뽑는다.
inspect.getmembers
함수를 통해 모듈의 함수, 클래스 이름을 key-value튜플의 리스트를 불러올 수 있다. 호출할 때 두 번째 인자로 inspect.isfunction
함수를 전달하여 함수만 가져올 수도 있다.
또는 데코레이터를 이용한다.
명령 패턴(command pattern)은 명령을 호출하는 객체가 명령을 통해 변형되고 접근되는 객체와 분리하여 호출하는 객체가 다른 객체의 정보를 몰라도 되도록 하여 결합성을 낮추는 패턴이다. 호출하는 객체를 호출자, 접근되는 객체를 수신자라 하고, 그 사이를 명령 클래스가 중간다리 역할을 한다. 명령 클래스는 추상 베이스 클래스와 이를 상속하는 여러 서브 클래스로 이뤄져있다. 명령 클래스는 수신자를 직접적으로 관리하기 때문에 수신자의 내부 구조를 알고 있어야 한다. 명령 클래스가 호출자로 전달되면 호출자는 적절한 상황에 명령을 수행하기만 한다.
이 경우에도 단일 추상 베이스 클래스를 함수로 바꾸거나 __call__
메서드를 구현한 클래스로 바꾸어 내부 상태를 유지하면서 함수처럼 실행할 수 있도록 할 수 있다.
또는 클로저를 이용한다.