Design Patterns 03.

Creational patterns - Abstract factory

by Dichter
추상 팩토리(Abstract factory)란?

우선 에릭 감마를 비롯한 4인방이 소개하는 추상 팩토리의 의도, 동기 그리고 활용을 읽어보자. 어렵지 않은 단어와 문장이니, 의미를 보며 정독해보자.


Intent

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.


Motivation

Consider a user interface toolkit that supports multiple look-and-feel standards, such as Motif and Presentation Manager. Different look-and-feels define different appearances and behaviors for user interface "widgets" like scroll bars, windows, and buttons. To be portable across look-and-feel standards, an application should not hard-code its widgets for a particular look and feel. Instantiating look-and-feel-specific classes of widgets throughout the application makes it hard to change the look and feel later.


We can solve this problem by defining an abstract WidgetFactory class that declares an interface for creating each basic kind of widget. There's also an abstrct class for each kind of widget, and concrete subclasses implement widgets for specific look-and-feel standards. WidgetFactory's interface has an operation that returns a new widget object for each abstract widget class. Clients call these operations to obtain widget instances, but clients aren't aware of the concrete classes they're using. Thus clients stay independent of the prevailing look and feel. There is a concrete subclass of WidgetFactory for each look-and-feel standard. Each subclass implements the operations to create the apropriate widget for the look and feel. Clients create widgets solely through the WidgetFactory interface and have no knowledge of the classes that implment widgets for a particular look and feel. In other words, clients only have to commit to an interface defined by an abstract class, not a particular concrete class.

A WidgetFactory also enforces dependencies between the concrete widget classes. A Motif scroll bar shuold be used with a Motif button and a Motif text editor, and that constraint is enforced automatically as a consequence of using a MotifWidgetFactory.


Applicability

Use the Abstract Factory pattern when

a system shuod be indenpendent of how its products are created, composed, and represented.

a system should be configured with one of multiple families of products.

a family of related product objects is designed to be used together, and you need to enforce this constraint.

you want to provide a class library of products, and you want to reveal just their interfaces, not their implementations.


설명에서는 위젯(Widget)들을 생성할 때를 예시로 들고 있다. 시스템이 위젯 객체들을 생성할 때에 추상 팩토리 패턴을 사용하였다.

위젯에는 종류가 여러 가지가 있으며, 그 종류마다 또 수많은 버전이 있다고 가정해보자. 위젯 별로 추상 클래스가 존재하고, 그 추상 클래스를 따르는 다양한 구체 클래스가 존재할 때, 사용자(개발자)는 위젯 객체를 생성할 때마다 각 위젯의 구체 클래스들의 특성을 알고 있어야, 상황에 알맞은 구체 클래스를 선택할 수 있다. 그런데 만약 각 위젯들이 연관성을 지니고 있어서, 한 위젯 객체가 다른 종류의 위젯 객체에 영향을 준다면 어떻게 될까? 사용자는 각 위젯의 연관성까지 파악하고 있어야 한다.


각 객체들이 서로 강하게 연결되어 의존도가 높고, 이 제약들을 반드시 지켜져야 할 때에,

사용자는 구체 클래스에 대해 알 필요가 없을 때에,

추상 팩토리 클래스를 사용하면 좋다.


추상 팩토리 예제

생성 패턴을 설명하는 글에서 보여줬던 Maze 예제를 추상 팩토리를 이용하여 리펙토링 해보자. (코드를 삽입할 수 있는 수단이 없어, GitHub 링크로 대체하였다.)

Abstract factory example code link


기존 Maze 코드에 새로운 요구사항이 추가된 상황이다. 기존 Maze에는 평범한 Wall, Door, Room으로 구성되어 있다. 하지만 기존 Maze 이외에도 사용자(개발자)가 선택할 수 있는 다양한 Maze를 추가하려고 한다. 마법으로만 열 수 있는 Door와 마법으로 가득 찬 Room으로 구성된 Maze, 폭탄이 존재할 수 있는 Room으로 구성된 Maze 등 여러 Maze를 만들어보자.


Maze를 구성하는 Wall, Door 그리고 Room이 각 테마에 맞게 통일성을 가지도록 제약을 걸고 싶으며,

사용자가 그 객체들의 구현에 대해 관심이 없을 때에 추상 팩토리를 사용하면 된다.


먼저, mapsite 디렉터리에는 각 요소들의 추상 클래스들을 정의해놓았다. 이렇게 추상 클래스들을 미리 만들어 놓으면 구체 클래스가 무엇인지 사용자는 알 필요 없이 추상 클래스에 선언된 메서드를 통해서 객체를 다룰 수 있다.

그리고 MazeFactory라는 추상 클래스를 만들어주었다. MazeFactory는 Maze 객체를 비롯한 Wall, Door 그리고 Room 객체까지 생성하고 반환하도록 명시해준다. 이를 통해 구체 팩토리 클래스는 정해진 메서드를 통해 자신의 테마에 맞게 생성하고 반환해야 한다.


이제 정해진 추상 클래스에 따라 각 테마에 맞는 구체 클래스들을 작성해준다. mapsite의 추상 클래스들을 이용하여 테마별 Wall, Door 그리고 Room을 구체 클래스로 만들어주고, 이 구체 클래스들을 이용해 객체를 생성하는 것은 구체 팩토리 클래스로 숨겨준다.


구체 팩토리 클래스는 자신의 테마에 어울리는 구체 클래스들을 이용하여 사용자에게 통일성 있는 구체 클래스들을 제공하며, mapsite 디렉터리의 추상 클래스들로 캐스팅하여 반환함으로 구체 클래스를 숨길 수 있다.


추상 팩토리 클래스 단점

추상 팩토리 클래스를 통하여 사용자가 직접 객체를 생성하지 못하도록 강제하고, 객체 그룹의 통일성을 줄 수 있는 추상 팩토리에는 단점이 있다.

추상 팩토리 클래스를 사전에 미리 정의하여 사용하고, 이를 이용해 구체 팩토리 클래스를 여러 군데에서 만들어 사용한다. 하지만 추상 팩토리 클래스는 이미 어떤 객체들을 반환할지 정의해놓는데, 만약 추후에 요구사항이 수정되어 몇 가지 요소들이 객체 그룹에 포함된다면, 추상 팩토리 클래스를 수정해야 추상 팩토리를 유지할 수 있다. 이렇게 추상 팩토리 클래스에 수정을 가하면, 모든 구체 팩토리 클래스를 다시 작성해야 하는 오버 코스트가 존재한다.


한스 홀바인대사들
한스 홀바인은 헨리 8세의 궁정 화가로 특히, 초상화에 능하여 신성한 것과 세속적인 것이 동등하게 그려진 종교적인 기풍 등으로 인해 독일 최대의 화가로 일컫는다.


1쇄. 2020.12.03.

keyword
작가의 이전글Design Patterns 02.