책정리/GoF 디자인 패턴 24

25장 동일 목적 알고리즘의 선택 적용 문제(Strategy 패턴)

문제 사례 설명 정렬을 하기 위한 알고리즘 여러 가지가 준비되어 있다. 여러 알고리즘 중에서 원하는 알고리즘을 선택해서 적용하는 것이 쉽도록 만들어주기 위한 설계 구조는 어떤 것이 바람직할까? 추가 개발된 알고리즘도 쉽게 반영할 수 있는 형태여야 할 것이다. 다양한 접근 방법 및 STRATEGY 패턴 기본적인 방법: 분기문에 의한 알고리즘 선택 적용 방식 [소스 25-1] 정수 배열 클래스 자체적으로 여러 정렬 알고리즘 중 선택, 적용 가능하도록 만든 소스 // basic.c #include #include using namespace std; #define DEFAULT_MAX_ITEMS 100 #define BUBBLE_SORT_ALGORITHM 1 #define QUICK_SORT_ALGORITHM..

24장 객체 상태 추가에 따른 행위 수행 변경 문제(State패턴)

객체의 행위 수행은 해당 객체의 상태에 따라 다양하게 변경될 수 있다. 이 때문에 객체의 행위 수행을 구현할 때에는 객체의 상태 값을 비교해서 서로 다른 행위를 수행하게 분기문을 두는 것이 보통이다. 그런데 여기서 문제는 이 같은 분기문의 경우 객체가 머무를 수 있는 상태의 종류가 새롭게 추가되었을 때 이를 반영하기 어렵다는 단점이 있다. 왜냐하면 분기문을 포함하는 경우에는 새로 추가된 상태를 반영하기 위해 기존에 작성된 프로그램을 분석해서 수정해야 하는 부담이 뒤따르기 때문이다. 이 장에서는 이런 관점에서 객체가 머무를 수 있는 상태가 새로 추가되더라도 추가된 상태를 포함해서 객체의 행위 수행 변경이 손쉽게 이루어질 수 있는 클래스 구조 설계에 대해 살펴본다. 문제 사례 설명 게임 플레이어가 임의의 공..

23장 One Source Multiple Use 문제(Observer 패턴)

이 장에서는 하나의 원본 데이터를 동시에 참조하고 있는 여러 개의 서로 다른 표현 양식간에 데이터 값의 변화를 즉시 반영할 수 있는 방법에 대해 알아본다. 문제 사례 설명 동일한 데이터를 여러 형태로 표현하였을 때, 어느 한 표현 양식의 데이터 값에 변경이 생기면 다른 모든 표현 양식에도 변경된 데이터 값을 즉시 반영해줄 수 있는 설계방법은 어떤 것이 있을까? 다양한 접근 방법 및 OBSERVER 패턴 동일한 데이터를 여러 곳에서 사용하는 경우를 One Source Multiple Use라고 부르는데 우리가 해결해야 하는 문제는 서로 다른 표현 양식간에 데이터의 일관성을 유지시켜주는 방법에 대한 것이다. 기본적인 방법: 원본 데이터에 대한 직접적인 참조 방식 가장 간단히 생각해볼 수 있는 방법은 모든 표..

22장 객체의 이전 상태 복원 문제(Memento 패턴)

문제 사례 설명 바둑에서 수를 무르는 경우, 바둑판은 이전 상태로 되돌아갈 수 있어야 한다. 다양한 접근 방법 및 MEMENTO 패턴 기본적인 방법: 계산을 통한 이전 상태 복원 방식 바둑판 객체는 현재의 바둑판 상태 정보를 저장, 관리한다고 하였다. 이를 위해 바둑판 객체는 [그림 22-1]에서 보는 것처럼 기본적으로 바둑돌이 놓여질 바둑판 정보와 흰 돌이나 검은 돌의 사석 수, 다음 둘 돌의 색깔, 총 두어진 수, 패의 위치, 맨 처음 둔 돌의 색깔 등을 데이터 멤버로 가지고 있다. 한 가지 생각해볼 수 있는 방법은 board_[][] 이차원 배열이 바둑 돌이 놓여진 수순 정보를 가지고 있다는 사실을 이용해서 계산을 통해 무르기를 수행하는 것이다. board_[][] 이차원 배열에서 각 항목들이 가진..

21장 M:N 객체 관계의 M:1 단순화 문제(Mediator 패턴)

객체지향 설계는 클래스나 객체간의 관계를 정의함으로써 주어진 문제의 해결책을 제시하게 된다. 이때 클래스나 객체간의 관계는 보통 그래프나 네트워크와 같은 형태를 이루게 되는데 이는 객체지향 설계의 특성상 전체 프로그램이 수행해야 하는 작업을 각 클래스가 객체가 적절히 분산해서 수행하기 때문이다. 문제는 클래스나 객체간의 관계가 너무 복잡하면 이를 이해하는 것이 어렵고, 구현 또한 힘들어진다는 것이다. 예를 들어 N개의 클래스가 서로 완벽하게 관계를 가진다면 방향성을 고려하였을 때 N*(N-1)가지의 관계가 존재하게 되는데, 이 값은 N이 커질수록 기하급수적으로 증가하게 된다. 관계의 수가 많아지게 되면 그 관계를 일일이 이해한다는 것은 거의 불가능하게 된다. 구현 측면에서도 각각의 클래스들이 순환 참조를..

20장 동일 자료형의 여러 객체에 대한 순차적 접근 문제(Iterator패턴)

프로그램을 작성하다 보면 여러 개로 구성되는 자료구조에 대해 각각의 구성 요소를 접근해서 필요한 작업을 수행해주어야 하는 경우가 종종 발생하게 된다. 예를 들어 배열의 각 구성 요소를 찾아다니면서 일괄적으로 작업을 처리한다든지, 트리를 구성하는 각 노드들을 방문해서 작업을 수행하는 경우가 그것이다. 이 같은 작업을 위해 대부분 for나 while과 같은 반복 문장을 수행하게 된다. 그런데 이 과정에서 문제는 자료구조마다 개별 구성 요소를 접근하기 위한 방법이 다르기 때문에 항상 각각의 자료구조에 맞추어 개별 구성 요소를 접근하는 프로그램을 따로 작성해야 한다는 점이다. 예를 들어 배열의 경우에는 인덱스 값을 증가시켜나가면서 개별 구성 요소를 접근해야 하는 반면, 트리의 경우에는 일일이 자식 노드나 형제 ..

19장 간단한 문법에 기반한 검증 및 작업 처리 문제(Interpreter 패턴)

컴퓨터 프로그램에게 완벽히 의미를 전달하기 위해서는 같은 표현이 서로 다른 의미로 해석되는 경우가 없어야 할 것이다. 또한 표현하고자 하는 모든 표현이 가능해야 하며 표현에 사용되는 기본 단어들도 명확하고 유연하게 정의되어야 할 것이다. 이 같은 조건들을 만족시키기 위해서는 우리가 일반적으로 사용하는 자연어와는 달리 철저히 정형화된 언어가 필요한데 이런 특성을 가진 언어를 형식 언어(Formal Language)라고 부른다. 형식 언어는 모든 표현들을 정형화시키기 위해 특정한 문법에 기초하게 되는데 이를 형식 문법(Formal Grammar)라고 한다. 컴퓨터 프로그램에게 완벽한 의미를 전달하기 위해서는 형식 문법에 기초한 형식 언어를 통해 자료를 표현해야 하는 것이다. 이같은 형식 문법과 형식 언어로 ..

18장 수행할 작업의 일반화 문제(Command 패턴)

소프트웨어 개발 과정에서 가장 큰 문제 중 하나는 개발해야 할 항목이 계속 추가되거나 변경되는 것이다. 심지어 처음에는 언급조차 되지 않았던 요구사항이 개발 막바지에 추가되어 소프트웨어의 설계를 송두리째 뒤흔들 경우도 종종 발생한다. 이런 사태가 발생하면 해당 프로젝트는 대부분 실패하거나, 개발이 완료된다고 하더라도 시간이 많이 지연되고 안정성이 떨어지는 등의 문제를 일으킨다. 이런 문제를 어떻게 회피할 수 있을까? 소프트웨어 공학에서는 프로토타이핑(Prototyping)이나 나선형 모델(Spiral Model)과 같은 방법들을 제시하고 있다. 그러나 이런 방법들을 적용시킨다고 해서 요구 사항의 추가나 변경으로 인한 문제가 없어지지는 않는다. 소프트웨어 설계에서 이 같은 유연한 설계가 필요한 부분들은 많..

17장 수행 가능 객체까지 요청 전파 문제(Chain of Responsibility 패턴)

어떤 객체에 서비스 요청이 전달되었는데, 이 객체에서는 해당 서비스 요청을 처리할 수 없다고 가정해보자. 이 경우 객체가 취할 수 있는 행동은 어떤 것들이 있을까? 크게 3가지 행동이 가능할 것이다. 하나는 오류나 예외 상황 발생으로 처리하는 방법 두번째는 전달된 요청과 가장 유사한 요청 처리 방식에 따라 작업을 수행해주는 방법 마지막으로 해당 서비스 요청을 가장 잘 처리할 수 있는 객체에게 요청을 전파해서 대신 처리하도록 만드는 방법 Client 입장에서 가장 편리하고 바람직한 것은 서비스 요청을 가장 잘 처리할 수 있는 객체까지 요청이 전파되어 처리가 이루어지는 세번째 방법일 것이다. 왜냐하면 이 경우에는 Client가 일일이 요청 처리 결과를 판별해서 또 다른 객체에게 재요청을 할 필요가 없고, 객..

15장 대리 객체를 통한 작업 수행 문제(Proxy 패턴)

프로그램에서 객체들은 저마다 수행해야 할 역할이 존재하는데 몇몇 객체들의 경우에는 너무 많은 역할을 수행해야 하거나, 부여된 역할을 수행하기 위해 여러 가지 복잡한 과정을 거쳐야 할 수 있다. 이 같은 경우 그냥 해당 객체가 모든 역할이나 작업을 수행하도록 하면 그 객체의 구현이나 유지, 보수는 굉장히 어려워질 것이다. 반면 실세계의 대리 체제처럼 복잡하거나 다양한 작업을 대신 수행해줄 수 있는 객체를 정의하고 사용한다면 전반적인 구현이나 유지, 보수 등이 오히려 손쉬울 수 있다. 왜냐하면 복잡하고 다양한 작업이 대리 객체에 의해 숨겨질 수 있기 때문이다. 문제 사례 설명 인터넷에서 웹으로 만화 서비스를 제공하는 경우 만화 서비스는 텍스트로 구성된 일반적인 웹페이지에 비해 데이터량이 많은 이미지 파일로 ..