Design Pattern for Smalltalk – Strategy

t_Dpsc_chapter05_Strategy_01

Strategy는 사용자가 라이브러리를 구축할 때 사용하는 일반적 개념과 가장 근접된 패턴이다. Sort(정렬) 알고리즘에는 여러가지가 있다. 수학적, 또는 논리적 차이를 가지는 이 알고리즘에는 대표적으로 Bubble, Quick 등이 있다. 이 알고리즘들을 상황에 맞게 사용할 수 있도록 정리해두고 싶다면 어떤 방법이 가장 좋을까? 이럴때 사용하는 것이 바로 Strategy 패턴이다.

Strategy패턴을 구성하고 싶을 때에는 먼저 대상들에게서 공통분모를 추출해서 추상클래스를 만드는 작업부터 시작하는것이 좋다. Sort 알고리즘은 원본 데이터를 받아 내부에서 정렬을 진행한 후 정렬된 결과를 반환한다. 이렇게 원본 데이터를 받아야 하는 인터페이스를 추상클래스에서 정의한 후 하위클래스에서 실제 동작할 내용을 구현하면 된다. 이렇게 하면 알고리즘을 사용해야 하는 context는 스스로가 원하는 알고리즘을 동일한 인터페이스로 골라서 쓰기만 하면 된다.

Strategy패턴은 그 구조상 State패턴과 유사성을 지닌다. 그렇다면 두 패턴은 어떤 차이가 있을까?

State패턴에서는 State의 하위클래스를 타입으로 취급하고 사용하게 권장한다. 반면 Strategy는 하위클래스를 연산으로 취급한다. Strategy패턴에서는 하위클래스의 추가가 타입의 증가로 취급되는것이 아니라 연산의 종류가 늘어나는 것으로 취급 될 것이다. 그리고 State는 context에서 state의 하위클래스가 가지고 있는 내부구현을 자세히 알지 않아도 반환값만 처리하면 되지만, Strategy는 context에서 Strategy의 하위클래스에 들어있는 내부구현 내용을 가능한 만큼 정확하게 숙지해야한다. 또한 context에서 관리 객체 변수가 참조하는 인스턴스가 상태에 따라 바뀐다면 State 패턴, 필요에 따라 지정해서 사용한다면 Strategy패턴으로 분류할 수 있다.

Design Pattern for Smalltalk – State

t_Dpsc_chapter05_State_01

디자인 패턴은 몇가지로 분류된다. 생성,구조,행위 의 3가지가 그것인데 특히 행위(behaviord) 패턴에 속하는 패턴들은 객체들 사이의 관계를 통해 어떤 결과가 일어나는지에 초점이 맞춰져 있다. State 패턴도 그 중 하나이다. State 패턴은 이름 그대로 “상태”를 객체로 표현하는 것이 목적이다. 하지만 중요한 것은 “왜 상태를 상수가 아닌 굳이 객체로 정의하는가”에 대한 것과 “이렇게 정의 된 상태는 어떻게 사용되는가”정도가 될 것이다.

State 패턴의 내용을 간략하게 정리해보자.

1. Client 는 context와 작업한다.
2.context 내부에서는 언제나 동일한 개념으로 State 인스턴스를 다룬다. (ex: state :: Open ( ) 호출 등)
3. context 내부에서 관리되는 State의 인스턴스가 상황에 맞게 교체되기 때문에 open 메서드의 동작결과는 바뀌게 된다.

이런 State의 동작원칙 덕분에 context 객체의 내부에서는 메세지를 다루는 작업에 대한 일관성을 확보하게 된다.

State 클래스의 추상클래스화를 통한 State의 다양한 상태를 수평적으로 늘일 수 있다. State가 표현해야 하는 각 상태를 상수로 정의하면 context 객체 내부에는 상수값을 판별해서 동작하는 내부조직이 직접 구현되어 있어야만 한다.

하지만 State 객체를 쓰면 상태에 따른 동작을 State 클래스군에서 책임지기 때문에 상태별 동작에 따른 코드를 새로운 Context 마다 복사해서 사용하는 대신에, 재사용을 쉽게하며 상태별 동작에 대한 코드의 유지보수를 보다 쉽게 할 수 있다. State의 하위 인스턴스는 그 자체로 상태의 타입을 의미하기 때문에 State의 인스턴스에게 동적인 리소스를 가지고 있게 구조를 만드는 것은 피하도록 하다. Context인스턴스 내부에서 관리되는 State 변수의 인스턴스 교환/관리는 context의 몫이지만 State 클래스군에 상태별 규칙을 넣어 State의 하위 클래스들간에 서로 상호작용하며 반응하게 할 수 있다면 보다 좋은 구현이 될 것이다.

Design Pattern for Smalltalk – Observer

t_Dpsc_chapter05_Observer_01

모든것이 객체(클래스)로 이루어져있는 Smalltalk 같은 시스템이나 객체지향 언어로 만들어진 어플리케이션은, 그 내부에 수많은 객체를 가지고 있게 된다. 당연히 물리적으로 보자면 바이너리(이진) 데이터의 나열에 지나지 않기 때문에 비-객체지향 언어로 만들어진 어플리케이션과 본질적인 차이는 없지만, 여기서는 논리적인 구조를 다루고 있으니 그 점은 넘어가도록 하자. 여튼 이렇게 수많은 객체사이에 특정 객체를 바라보는 객체를 B라고 하고 특정 객체를 A라고 가정하자. A의 내부에서 변수의 내용이 갱신되었을 때 이 내용을 B에게 알려줘야 하는 경우가 되었다면 어떻게 해야할까? 그리고 이 B가 한개가 아니라 복수로 존재한다면 A는 어떻게 해야할까? observer패턴은 이런 경우를 풀어내기 위해 고안된 방법이다.

객체지향은 사람의 생각을 기본 모델로 해서, 생각에서 이루어지는 관계를 체계적이고 효율적으로 정리해서 구현 및 적용한 방법이다. 그렇기 때문에 이 패턴 역시 사람과의 관계에 비추어서 생각 해 보면 조금 이해하기 쉬울것이다. 나는 무언가를 가지고 관리하는 사람이고, 이런 나와 관련된 업무를 하는 다른사람이 여럿 있다고 가정하자. 이 때 다른 사람들은 내 무언가의 상태가 변화될 때 영향을 받는 업무라고 할 때 어떻게 해야 효율적일까.

당연히 나는 무언가의 상태를 관리하며 다른 사람에게 상태의 변화를 통지해주는게 가장 효율적인 방법이 될 것이다. 이 때의 나를 subject라고 하고 다른 사람을 observer라고 이해하면 된다.

observer패턴의 진행을 간단하게 보면 다음과 같다.

1. data 객체가 자신을 창조하는 객체들에게 notification을 보내서 자신의 상태변경을 알린다.
2. notification을 받은 객체는 data 객체내에서 갱신된 자료를 가져온다.

이 때 data객체가 자신을 참조하는 객체의 목록을 관리한다는 점에서는 proxy 패턴의 reference counter와 통하는 부분도 있다.

t_unnamed0

data객체를 참조하는 참조객체의 수가 1 이상일 때 data 객체에 최초의 데이터 요청이 오면 data객체 내에서 데이터를 캐싱해서 관리하고, 참조객체의 수가 0이면 data와 DB의 연결을 끊어서 리소스의 낭비를 줄일 수도 있다.