본문 바로가기
SW

GoF의 디자인 패턴(Design Patterns: Elements of Reusable Object-Oriented Software) - 2장 사례 연구:문서 편집기 설계(2.6)

by 라꾸스떼(YR) 2020. 4. 12.
반응형

[2.6 다중 윈도우 시스템 지원]

[추상 팩토리 패턴을 사용할 수 있을까요?]

윈도우 시스템 간의 이식성은 앞에서 본 룩앤필 표준에 대한 독립성과는 사뭇 다른 점이 있다. 추상 팩토리 패턴을 적용할 때는 각 룩앤필별로 정확한 위젯 클래스를 정의할 것이라고 가정했다. 즉, 각 위젯별로 하나의 추상 클래스를 추출할 수 있어 추상 팩토리 패턴의 사용이 가능하다. 윈도우 시스템은 각 회사마다 서로 다른 여러 개의 클래스 게층을 이미 가지고 있는데, 이 계층이 서로 호환 가능하다고 볼 수 없기 때문에 각각 위젯별로 공통의 추상 클래스를 정의할 수 없다. 이때는 추상 팩토리 패턴을 적용할 수 없으므로, 제품이 갖는 인터페이스에서 공통된 연산을 정의하는 별도의 위젯 계층을 만들어야 한다. 그래도 다행인 점은 룻앤필 표준에서도 그랬듯이 윈도우 시스템의 인터페이스 역시 심각하게 다르지 않다는 것이다. 단, 하는 일은 비슷하지만 구현하는 방법은 완전히 다르므로 윈도우가 하는 일에 대한 추상화와 이를 구현하는 방버의 추상화를 분리시켜야 한다. 윈도우가 하는 일이란 윈도우 시스템의 인터페이스를 의미하고, 이를 구현하는 방법이란 실제 윈도우 시스템이 제공하는 프로그래밍 인터페이스를 의미한다.

 

[구현 종속성을 캡슐화]

화면에 표시되는 글리프나 글리프 구조를 Window 클래스. 다음과 같은 것들을 캡슐화.

-기본적인 기하학적 도형을 그릴 수 있는 연산을 제공한다.

-아이콘 상태가 될 수 있고 아이콘 상태에서 해제될 수도 있다.

-크기 변경이 가능하다.

-요청이 있을 때 콘텐츠를 (다시) 그린다.

윈도우 시스템과 상관없이 서로 다른 윈도우 시스템에서 기능성을 확장할 수 있다.

이를 위한 다음 두가지의 극단적인 원칙

1.기능성의 교집합으로만 인터페이스를 정의

2.기능성의 합집합으로만 인터페이스를 정의

이 두방법은 모두 문제가 있기 때문에, 그 중간 방법을 선택해야 할 것이다.

Window는 추상 클래스이고 Window를 상속하는 서브클래스들이 사용자가 다룰 서로 다른 종류의 윈도우를 지원한다. 예를 들어, Window 서브클래스는 응용프로그램 윈도우, 아이콘, 경고 창 등 다양한 종류의 윈도우를 지원한다.

윈도우 추상화는 반드시 기존의 윈도우 시스템이 제공하는 방법으로 구현되어야 한다. 한 가지 방법은, Window 클래스와 서브클래스들을 각각 윈도우 플랫폼마다 서로 다른 버전으로 구현하는 것이다. 그러나 이때는 유지보수가 매우 어렵다. 또 다른 방법은 Window 계층의 각 클래스에 대해 구현 플랫폼별 서브클래스를 모두 생성하는 것이다. 이 방법을 쓸 때에는 서브클래스의 수가 너무 많아진다는 문제가 발생한다. 그리고 방금 말씀드린 두 방법은 공통적인 또 다른 단점을 가지고 있다. 프로그램을 컴파일한 후에는 윈도우 시스템을 변경할 수 없다는 것이 그 단점이다. 결국 윈도우 시스템마다 별도의 실행 파일을 유지할 수 밖에 없다. 또 다른 방법으로, 서식 설정이나 장식을 설계할 때 썼던 방법처럼 다양성이 존재하는 부분을 별도로 캡슐화하면 된다. 이때 다양성을 갖는 대상은 윈도우 시스템별 구현이다. 윈도우 시스템의 기능을 하나의 인터페이스 객체로 캡슐화했다면 우리는 Window 클래스와 이의 서브클래스를 구현할 때 이 인터페이스를 따라서 구현해야 한다. 적절한 윈도우 시스템을 캡슐화한 객체를 윈도우 시스템 쪽으로 전달해 주면 된다. 심지어 런타임에도 윈도우를 설정할 수 있다.

 

[Window와 Windowlmp]

WindowImp는 추상 클래스이고, 윈도우 시스템에 종속된 코드를 캡슐화한다. Lexi가 특정 윈도우 시스템에서 제대로 동작하도록, 각 윈도우 객체를 WindowImp의 서브클래스 인스턴스로 설정할 것이다. 윈도우 시스템 구현이 WindowImp 클래스 속으로 숨어 들어갔기 때문에, 이제는 Window 클래스를 윈도우 시스템에 종속적인 내용으로 더럽히지 않아도 된다.

<WindowImp 서브클래스들>

<WindowImp를 써서 Windows 설정하기>

아직 다루지 않은 문제는 적당한 WindowImp 서브클래스의 인스턴스를 어떻게 Window 쪽에서 얻는가 하는 문제이다. 즉, _imp 멤버 변수를 언제 초기화하고, 어떤 윈도우 시스템을 사용해야 하며, 누가 알고 있어야 하는지와 관련된 문제이다. 몇가지 해결 방법이 있지만, 여기서는 추상 팩토리 패턴을 사용하는 방법만 살펴보자.

먼저, WindowSystemFactory 클래스를 만들어서 윈도우 시스템별 구현 객체의 각 종류를 생성하는 인터페이스를 정의한다. 그러고 나서 각각의 윈도우 시스템마다 필요한 팩토리를 정의한다.

 

[가교 패턴]

Window 클래스와 WindowImp 클래스 간의 관련성은 가교 패턴의 한 예이다. 서로 독립적으로 확장되지만 함께 동작해야 하는 개념들을 별도의 클래스 계층으로 분리하는 것이 가교 패턴의 목적이다. 이렇게 두 개의 계층으로 분리할 때는 두가지의 기준을 세워야 한다. 하나는 논리적 개념에 해당하는 윈도우이고, 다른 하나는 그 윈도우에 대한 서로 다른 물리적 구현이다. 가교 패턴을 적용하면, 윈도우 시스템에 종속적인 구현과 전혀 상관없이 논리적인 윈도우 추상화를 확장할 수 있고, 그 반대로 추상적 개념과 무관하게 새로운 윈도우 시스템의 구현도 추가할 수 있다.

반응형

댓글