Design Pattern for Smalltalk – Prototype

t_Dpsc_chapter03_Prototype_01

Prototype 은 패턴을 Prototype으로 설계된 클래스의 부사에 대한 내용이다. 좀 뜬금없는 예가 되겠지만 Lazarus 를 예로 들어보자. (Lazarus는 Open Source 프로젝트이며 fpc (free passal compileer)를 이용하는 RAD 틀이다.)

Lazarus의 실행화면에서 새 프로젝트를 생성하고 상단의 팔레트를 보자. 이 팔레트에서 button을 하나 드래그해서 Form 위에 놓아보자. 쉽게 확인할 수 있듯이 button 이 하나 놓여졌다. Prototype 패턴은 이를 위한 패턴이다. 간단한 개념이지 않은가?

팔레트는 Client 가린다. 팔레트의 역할은 button의 Prototype의 Tbutton 클래스로 부터 인스턴스를 만들어 Form의 아래쪽으로 넣는 역할을 한다. 지금의 설명처럼 Tbutton 클래스는 button 인스턴스의 Prototype이 된다. (사실은 Tbutton의 인스턴스를 복사해서 인스턴스를 만드는게 더 정확한 개념이지만 지금은 설명을 위해 넘어가자)

Form 위에 여러개의 button을 넣는 경우 button의 label property는 자동으로 바뀌어 생성된다. 이렇게 복사되는 인스턴스의 상태(status)를 변경하는 데에는 팔레트에서의 변경과 놓이는 form 에서의 변경 등 두가지 정도의 경우가 있다. 이 두가지 경우에 있어서 인스턴스에 대한 초기화 매서드에서 변경을 처리하는 경우와, 놓이는 form 에서 호출하게 되는 인스턴스의 메서드에 인자를 전달해서 변경을 만들어내는 방식이 고려될 수 있다.

Design Pattern for Smalltalk – Factory Method

t_Dpsc_chapter03_FactoryMethod_01

클래스에 객체의 인스턴스를 생성해 내기위한 인터페이스 (메서드)를 정의하지만 어떤 클래스의 인스턴스를 생성할지에 대한 걱정은 추상클래스의 하위클래스에서 결정하는 패턴이다. 추상클래스에는 virtual 인터페이스만 있고 구현은 하위클래스(구체클래스)에서 이루어지며 인스턴스의 원래 클래스도 구현부에서 결정하게 된다.

(* Smalltalk에서는 어떻게 추상클래스와 구체클래스를 구분해서 정의하는가 – 조사필요)

ex)word와 excel의 “새문서 생성”등의 경우를 생각해보자.

둘 다 동일한 메서드를 쓸 수 있다.

Document Class >> create Document Object

다만 메서드 전송 후에 반환되는 인스턴스의 종류는 틀리다. 이런 경우를 위해서 사용된다.

Design Pattern for Smalltalk – Abstract Factory

t_Dpsc_chapter03_AbstractFactory_01

추상팩토리 패턴의 본질적 의미는 하위클래스에서 필요한 인터페이스의 추상적 선언에 있다.추상클래스 자체는 동작에 있어 어떠한 직접적인 의미도 없지만 인터페이스의 원래 형태에 대한 틀을 정의한다는 점이 특징이다.

추상팩토리 패턴에서 구현되는 하위클래스인 구체적 클래스는, 상위 클래스의 인터페이스를 따르기 때문에 구현된 구체적 하위클래스를 직접 사용하는 다른 코드 내에서 선택제어문 등을 줄일 수 있다. 다만 smalltalk는 타입이 의미가 없는 언어이기 때문에 인터페이스 설계에서 부담이 적지만 CTT등의 타입을 필요로 하는 (typed) 언어의 경우는 인터페이스를 좀 더 엄격하게 설계해야 할 필요가 있다.

추상팩토리 패턴은 무언가 결과를 얻어내는 코드에 있어 it문 등의 불필요한 제어문의 사용을 줄여서 프로그램의 흐름을 좀 더 간결하게 정리할 수 있다는 데에 가장 큰 의미가 있다. 프로그램 내의 호직을 분기없이 단순화하는 과정은 결과적으로 유지보수까지의 고민으로 이어지게 된다.

추상팩토리 패턴의 구현과 사용은 크게 세가지로 나눌 수 있다.
– Constant Method 방법
– 부품 카탈로그 방법
– 단일 팩토리 클래스 방법

각 방법에 대해 간단히 알아보도록 하자.

Constant Method
Constant Method 방법은 추상클래스 (상위클래스)에 하위클래스 호출시 사용 될 메서드의 구현을 공통된 코드로 구현하고, 하위클래스 에서는 공통된 코드에서 호출되는 내용을 개별적으로 직접 구현함으로서 추상계층을 한번 더 내부적으로 구현해서 유지보수를 편하게 한다는 차이점이 있다. 내부적으로 Public 메서드가 Private 메서드를 도출해서 Public 메서드를 통해 반환값을 처리하게 하는 논리 순서를 구현하는 방법이다. 이 방법은 분류별로 메서드를 만들어야 하며, 분류가 추가되는 경우 상위클래스 및 하위클래스에 추가되는 분류에 따른 메서드를 모두 작업해 주어야 한다.

부품 카달로그
부품 카달로그 방법은 상위클래스 및 하위클래스군에 반환값의 분류별로 메서드를 각각 만드는 것이 아니라, 하나의 메서드와 메서드의 인자에 따른 반환값의 정보를 가지고 있는 카탈로그를 구체적 하위 클래스의 내부에서 각각 유지함으로서 구조를 보다 단순하게 만든다. 이 방법은 반환값 및 인자의 분류가 추가되어도 구조의 큰 수정 없이 카달로그의 값만 조정함으로서 프로그램을 보다 쉽게 확장할 수 있다는 장점이 있다. factory를 사용하는 사용하는 코드에서는 동일한 인자를 넣어도 factory 객체가 창조하는 구체적 하위클래스에 따라 각각 다른 반환값을 얻게 된다.

Constant method 방법은 원하는 분류에 따라 각각 다른 메서드를 사용해야 하지만 부품 카달로그 방법은 동일 메서드에 인자만 다르게 하면 된다는 차이점이 있다. 그리고 추상 상위클래스에서 인자에 따른 값을 반환하는 메서드의 동작까지 선언하면 구체적 하위클래스에는 각 클래스의 카달로그 내용만 별도로 유지하면 되는 구조를 가지게 된다.

단일 팩토리 클래스 방법
단일 팩토리 클래스 방법은 별도의 하위클래스를 선언하지 않고 추상 클래스를 취급하던 상위 클래스에 연산을 필요로 하는 메서드와 연산의 대응값을 가지고 있는 값의 카달로그를 모두 포함시키는 방법이다. 하위클래스의 인스턴스를 사용하는것이 아니라 단일 클래스의 인스턴스를 생성할 때 별도의 메서드를 이용해서 원하는 결과 집합을 반환하는 인스턴스를 바로 생성해서 사용하는 방법이 된다. 이 경우 factory를 사용하는 코드에 변화는 없다. 단일 클래스는 클래스 메서드로 인자를 필요로 하지 않는 각 집합별 메서드를 가지게 된다.

var := factory Class initMethod

위의 구문을 통해 initMethod 에 해당하는 카달로그를 가지고 있는 var 객체를 가질 수 있으며 이 객체를 통해 원하는 값을 얻을 수 있게 된다.