패턴 1

programing/ETC 2009.04.14 20:00

Story 00 들어가기 전에

Story 01 어떤 코드가 잘 만들어진 것일까

Story 02 C로 개발하면 안되나요?

Story 03 공통점 묶기, 조금만 알기

Story 04 회사에선 사원, 군대에선 군인, 편의점에선 손님

Story 05 체계적인 정리법이 필요하다

Story 06 컴퓨터는 생각보다 훨씬 빠르다

Story 07 패턴은 이름 붙여진 것일 뿐

Story 08 빠르게 더 빠르게

Story 09 이쁜 코드 만들기

Story 10 쉬운 그림으로 이해하기

Story 11 객체 생성은 객체 생성 전문가에게 (팩토리 패턴(Factory Pattern))

Story 12 관점의 차이가 곧 객체 생성의 차이 (추상 팩토리 패턴(Abstract Factory Pattern))

Story 13 필요한 것은 알아서 만들자 (팩토리 메소드 패턴(Factory Method Pattern))

Story 14 순서를 정리하면 시점이 보인다. (템플릿 메소드 패턴(Template Method Pattern))

Story 15 복잡한 조립은 전문가에게 맡기자 (빌더 패턴(Builder Pattern))

Story 16 오직 하나뿐인 그대 (싱글턴 패턴(Singleton Pattern))

Story 17 너의 쌍둥이가 필요해 (프로토타입 패턴(Prototype Pattern))

Story 18 수정할 수 없는 너무 안정적인 당신 (어댑터 패턴(Adaptor Pattern))

Story 19 무슨 일이 생기면 바로 알려줘 (옵저버 패턴(Opserver Pattern))

Story 20 한가지 탐색법만 기억하라 (이터레이터 패턴(Iterator Pattern))

Story 21 복합구조도 접근법은 하나 (컴포지트 패턴(Composite Pattern))

Story 22 난 기분에 따라 행동이 달라져 (스테이트 패턴(State Pattern))

Story 23 골라쓰는 알고리즘 (스트래티지(정책) 패턴(Strategy Pattern))

Story 24 공유되는 정보와 대리인 (프록시 패턴(Proxy Pattern), 플라이 웨이트 패턴(Flyweight Pattern)

Story 25 행동만 따로 떼어보자 (커맨드 패턴(Command Pattern))

Story 26 꾸미는 방법도 여러가지 (데코레이터 패턴(Decorator Pattern))

 


Story 00

들어가기 전에

이 글은 ‘패턴 그리고 객체지향적 코딩의 법칙’(이하 원문)이라는 책을 보고 정리해 놓은 글입니다. 원문에서는 이해하기 힘든 개념들(디자인 패턴과 객체지향적 사고방식)과 개발을 할 때 생기는 노하우가 주된 내용이라면 이 글은 원문에서 쉽게 설명된 개념들을 정리해 놓았습니다. 요약을 하는 과정에서 원작자의 의도를 다소 잘못 이해하고 정리했을 수도 있으니 이점은 양해바랍니다. 이 글은 요약을 해놓은 글이기 때문에 원문에서 다루었던 위트있는 문장들이나 상황에 대해서는 다루지 않았습니다. 보다 재미있게 글을 읽으시고 싶은 분들은 원문을 읽어보실 것을 추천합니다.

 

이 글을 읽으실 때 (Eclipse : )’으로 처리된 부분은 개인적인 생각과 다른 서적(Gof 디자인패턴, 헤드퍼스트 디자인페턴)을 적어 놓은 것으로 원저자의 의도와는 다소 다를 수 있습니다. 이 뒤에서부터는 편의상 경어를 생략하겠습니다.

 

 

Story 01

어떤 코드가 잘 만들어진 것일까

구구단7단을 짜달라는 요구사항이 있다 당신은 어떻게 개발하겠는가?

1) printf를 9번이용한다.

2) for(i=1;i<10;i++);를 사용한다.

3) class를 정의하고 메소드를 제공한다.

추가된 요구사항 7단을 99까지 출력하시오. 여기까지 for문을 이용한 구구단은 유요하다.  두번째 추가 요구사항 m*n 구구단table을 출력하시오. 아직도 for문을 이용한 구구단은 유요하다. 하지만 이를 배포할 때는 문제가 되는 것이다. 함수를 배포하는 것과 클래스를 배포하는 일은 같지 않은 것이다. 구조적 방식이 잘못된 방식은 아니다. 다만 실수하기가 쉽고, 수정하기가 조금 더 힘이들 뿐이다. 하지만 프로라면 좀더 실수가 적고, 수정하기 편한 방식을 따라가는 것이 좋지 않을까?

(Eclipse : 솔직히 나라면 지금이라도 for문을 이용해서 짤 것 같다. Class를 만드는 일은 단순한 기능에 대한 오버해드가 발생하는 것이 아닌가? 기능이 추가되면 그때 Class화 해도 될 것 같다.)

 

 


Story 02

C로 개발하면 안되나요?

객체지향 프로그래밍은 구조적 프로그래밍이 가지는 단점을 보완하면서 더 큰 프로그램을 개발하는데 적합한 개념과 여러가지 언어적 지원이 덧붙여진 연구와 경험의 산물이다. 객체지향적 프로그래밍이 좀더 수정하기 쉽고, 실수할 경우가 적기 때문이다.

 

 

Story 03

공통점 묶기, 조금만 알기

공통점 묶기와 조금만 알기는 객체지향 언어에서 상속, 다형성, 캡슐화보다 더 중요한 개념이다.(Eclipse: 공통점 묶기와 조금만 알기는 상속, 다형성, 캡슐화를 좀 더 쉽게 풀어쓴 말에 불과하다고 생각한다.) 공통점을 묶고 조금만 알기 위해 노력하다 보니 상속, 다형성, 캡슐화가 필요하게 되고 더불어 추상화, 일반화라고 세분화도 저절로 이루어지는 것이다.

 

 

Story 04

회사에선 사원, 군대에선 군인, 편의점에선 손님

(Eclipse: 왠지 제목부터 인터페이스를 이야기 할 것 같다는 느낌이 들었다.)

객체지향 프로그래밍의 기본 단위는 클래스이다. 모든 클래스는 단 하나의 책임을 가지는 것이 좋다. 각자의 책임을 가지는 클래스를 우리가 어떻게 조립하는가에 따라 결과물이 달라진다. 클래스를 조립할대 서로 다른 클래스를 연결하는 방법은 결합도를 증가시킨다. 이는 인터페이스를 클래스 사이에 놓아서 해결할 수 있다. 그 모든 기본은 ‘조금만 알기’에 있다는 점을 잊지말자.


Story 05

체계적인 정리법이 필요하다

객체지향은 클래스를 통해 역할을 명확히 함으로써 시작한다. 이 역할을 통해 객체지향은 각 클래스 사이의 관계를 논리적으로 사람이 이해하기 쉽도록 만들어준다. 새로운 기능을 소스에 추가하거나 기존 기능을 변경할 때도 논리적으로 먼저 이해를 하고 접근한다면 쉽게 원하는 위치에 정확한 코드를 넣을 수 있을 것이다. 객체지향은 설계부터 코딩까지 모든 부분에 걸쳐서 적용될 수 있는 궁극의 정리 정돈 방법임을 명심하자.

 

 

지저분한 코드

깨끗한 코드

순환

원인

-   무책임한 개발자

-   Case By Case로 땜빵하는 코드

-   소스의 이해 부족으로 인한 잘못된 수정

-   높은 결합도로 인한 부작용

-   문서와 다른 소스

-   ~로 시작되는 구차한 변명

-   커뮤니케이션의 부족

-   다른 개발자들에게 API를 제공한다는 마음으로 개발하라

-   남이봐도 쉬운 코드를 만들어라

-   자신만의 코드만 보지 말라

-   기존의 코드와 통일성 있는 코드를 작성하라

-   커뮤니케이션 하라

-   항상 ‘1년 뒤에 이 소스를 본다면?’이라고 생각해라

-   리팩토링하라

-   죽은 문서는 만들지 말라

(Eclipse : 언제나 시작이 중요하다 좋은 시작은 좋은 결과를 도출하기 마련이다.)
Story 06

컴퓨터는 생각보다 훨씬 빠르다

소프트웨어 개발은 점점 구조와 알기 쉬움을 중시하는 방향으로 발전해 나간다. 하드웨어가 발전했고 도구들이 발전했고 개발 언어들도 발전했다. 우리는 시장의 요구에 맞추어 보다 생산성 있는 방법을 사용해야 한다. 물론 메모리와 퍼포먼스는 개발자가 반드시 익혀 잘 사용해야 할 기본적인 요소지만 이런 큰 흐름을 망각한 채 퍼포먼스 중독증이나 메모리 중독증에 걸려서는 안될 것이다.

 

(Eclipse : 여기서 말하는 퍼포먼스 중독증이나 메모리 중독증은 임베이디드나 서버프로그램과 같이 성능이 최우선시 되는 프로그램을 제외한 일반 어플리케이션프로그램들에 대한 것을 말한다. 퍼포먼스가 중요시되는 프로그램에서는 당연히 퍼포먼스를 최우선으로 생각하고 코딩해야 한다는 것이다.)

 

 

Story 07

패턴은 이름 붙여진 것일 뿐

완벽함이란 더 이상 무엇인가를 더할 것이 없을 때 이루어지는 것이 아니라, 더 이상 무엇인가를 뺄 것이 없을 때 이루어진다.                                                                  – 앙뜨완느 마리 로제 드 생떽쥐베리

 

(내가 그의 이름을 불러 주기 전에는 그는 다만 하나의 몸짓에 지나지 않았다. : 김춘수<꽃>)

->(GoF가 그 패턴의 이름을 불러 주기 전에는 그 패턴은 다만 하나의 코드에 지나지 않았다.)

 

디자인 패턴이라는 말이 존재하기 전부터 개발자들은 객체지향 프로그래밍을 해왔다. 디자인 패턴을 논할 때 곡 빠지지 않는 책이 있으니 바로 ‘GoF(Gang of Four라는 객체지향의 대가4인을 말한다.)의 디자인 패턴’이다. 이분들을 통해 디자인 패턴이 정리되어 널리 발표되긴 했지만 특정 형태의 코드를 XX패턴이라고 부르기 전부터 그런 형태의 코드가 사용되어 왔다는 점을 알아야 한다. -> 디자인 패턴은 코드 리팩토링의 결과물일뿐.

 

‘GoF 디자인패턴’의 요지는 간단한다. 어떨 대 이런 구조가 사용되면 좋다고 간결하게 설명한다. 하지만 실전에서는 특정 디자인 패턴만으로는 개발을 완료할 수 없다. 상황에 맞는 디자인 패턴을 적용 시키는 일도 좋지만, 디자인패턴에 개발을 맞추는 것은 바람직하지 않다.

 


※ 나고수의 코딩 원칙

-         클래스가 꼭 필요한 변수와 함수만을 가지고 있는가?

-         클래스 사이의 연관성이 너무 높지 않은가?

-         중복된 코드가 너무 많지 않은가?

-         클래스가 너무 크지 않은가?

-         코드를 이해하기 쉬운가?

-         변하는 부분과 변하지 않는 부분은 무엇인가?

 

Story 08

빠르게 더 빠르게

※ 코딩속에서 디자인하라

리팩토링은 반드시 필요하다. 리팩토링은 시간을 내서 해야 할 작업이 아니라 구현의 한 부분이어야 한다. 하지만 코드 분해와 재조립의시간이 오래 걸린다면 리팩토링을 시도하기가 두려울 것이다. 자신의 코딩에 자신감을 가질 필요가 있다. 코드의 품질은 경험과 비례한다.

 

※ 퍼포먼스를 높여라

(Eclipse : 프로그램의 퍼포먼스를 이야기 하는 것이 아니라 개발자 본인의 퍼포먼스(속도)를 높이라는이야기)

-         코딩 중에는 마우스를 최대한 만지지 마라.

-         자신이 사용하는 툴의 모든 단축키를 외워라.

-         디버깅하기 쉽도록 코드를 작성하라.

-         반복되는 작업을 편하게 해줄 도구를 찾아라.

-         목적지로 가는 가장 빠른 길을 탐색하라.

-         구현 중에는 흐름을 끊지 말아라.

 

진정한 개발자는 개발을 즐긴다. 코드는 개발자의 생각을 표현해 내는 최종 매개체이다. 자신의 가치를 높이기 위해서는 이 표현의 속도를 높여야 한다. 정해진 시간에 많은 일을 할 수 있다면 여러분은 더 많은 일과 경험을 쌓을 수 있을 것이다. 시간에 쫓기기보다는 시간을 관리할 수 있을 정도까지 퍼포먼스(코딩속도)를 끌어올여야 한다.

 

 


Story 09

이쁜 코드 만들기

Martin Fowler(리팩토링의 저자) :  컴퓨터가 이해할 수 있는 코드는 어느 바보나 다 만들 수 있다.

좋은 프로그래머는 사람이 이해할 수 있는 코드를 만든다.

아무리 멋진 개념과 패턴 그리고 여러 가지 테크닉으로 만들어진 코드라도 극악의 가독성을 가진다면 수정이나 변경이 힘들 것이다. 특히 여러 개발자가 공동 작업을 하는 경우는 더 많은 문제를 일으킬 수 있다. 동료 개발자끼리 코드의 형태가 전혀 다르다면 서로 도와 줄 수도 없을 뿐더러 점점 코드적으로 고립되어 갈 것이다. 또 이는 코드 리팩토링과 기능확장에도 용의하지 않다.

 

코드는 개발자의 얼굴이다. 얼굴이 지저분한데 누가 호감을 가지겠는가. 사람도 항상 관리하고 깔끔하게 하고 다녀야 하는 것처럼 코드도 한번 만들고 나면 다신 안보는 것이 아니라 만들어 놓고부터 시작이라는 마음가짐을 가져야 한다.

 

 

※ 네이밍

변수나 함수이름을 명시할 때 의미없는 기호나 문장을 사용하지 말고, 확실히 단어로서 의미를 분명히 전달해 줄 것을 권장한다. 변수의 이름이 길어진다고 프로그램이 느려지는 것은 아니니 걱정하지 말자. 변수나 함수, 클래스 이름만 딱 봐도 ‘어떤 역할을 수행하는 구나’라고 이해가 될 수 있도록 네이밍해 해주는 센스를 발휘한다면 후에 봐도 쉽게 코드를 이해할 수 있을 것이다.

(Ex. nCount, nValue, nMax는 무엇에 관한 카운트, 값, 최대값인지를 알 수 없다. 이는 제대로 명시 해주는 것이 좋다.)

 

 

Prefix 붙이기(Eclipse : 헝가리안 표기법(Hungarian notation)

(Eclipse : 최근에는 개발툴이 좋아져서 굳이 Prefix를 붙이지 않아도 된다고 생각한다. 최근 MS에서도 헝가리안 표기법을 지양하자고 한다. 하지만 팀에서 헝가리안 표기법을 따른다면 굳이 이를 지양할 필요도 없을 것이다. 코딩은 가독성이 중요하기 때문에 팀의 스타일에 맞추는 것이 중요하다고 생각한다. 참고로 헝가리안 표기법은 WinAPI개발자 중 한사람이 시작하였는데, 그 사람이 헝가리 사람이어서 헝가리안 표기법이라는 명칭을 사용하였다고 한다.)

 

Prefix를 사용하게되면 변수에 자료형을 명시해놓기 때문에 변수의 특성을 파악하기에 좀더 편리하다. 혼자서 개발을 한다면 자신이 가장 잘알아 볼 수 있는 표기법을 사용하는 것이 좋고, 공동개발을 한다면 모든 팀원들이 가장 쉽게 지킬 수 있는 표기법을 사용하는 것이 좋다.

※ 탭 들여쓰기 & 공통 타입 묶기

(Eclipse : 이 또한 개발하는 상황에 맞춰야한다. 팀이 굳이 변수에 들여쓰기를 하지 않는데, 본인만 그게 보기편하다고 변수에 들여쓰기를 할 수는 없는 것이다. 내 생각에는 변수들여쓰기가 확실히 보기 편하지만, 안쓰는 사람이 더 많기 때문에 무엇이 좋다고 할 수는 없는 것 같다. 하지만 확실히 공통 타입은 묶어서 관리하는 것이 보기에 편할 것 같다.)

 

 

※ 클래스 헤더 구성

클래스 헤더에 함수나 변수를 작성할 때 가장 중요한 부분을 맨 위에 배치하고 덜 중요한 부분을 맨 밑에 배치하는 것이 좋다. 클래스의 접근자는 public, protected, private 순으로 접근 범위가 달라진다. 접근 범위가 가장 넓고 해당 클래스의 사용하는 다른 코드들에서 빈번히 호출이 일어나는 public을 제일 먼저 쓰고, 생성자는 public의 제일 마지막에 위치시킨다. public 다음으로 해당 클래스의 자식 클래스들이 overriding(오버라이딩) 할 수 있는 함수들을 그 다음에 위치시키며 마지막으로 클래스 내부에서만 사용하는 private을 제일 마지막에 위치시킨다.(변수의 경우 객체지향에서 직접노출 시키는 것은 좋지 않으므로 제일 마지막에 위치시키는 것이 좋을 것이다.) 또 관련있는 함수들은 가까이 위치시키는 것이 좋다.

 

‘{’의 위치

(Eclipse : 개인적으로 2안을 좋아하지만 1안을 따르는 사람도 많다. 이것도 팀원들이 주로 사용하는 쪽으로 맞춰서 개발하는 것이 좋을 것 같다.)

1안

2안

if( exp ){

             

}

if( exp )

{

             

}

 

※ 함수의 흐름을 간단하게

“이함수가 뭐하는 함수에요?”라고 물었을 때 “이 함수는 A기능도 하고 조건에 따라 B기능도 하고 에러가 났을 때는 C의 기능도 해요”라고 대답해야만 한다면 당장 그함수를 A, B, C 3개의 함수로 나누어라. 컴퓨터는 코드가 아무리 복잡하더라도 모두 이해하고 잘 처리하지만 사람은 그렇지 못하다. 함수 하나에 한가지의 기능만을 부여해서 함수의 재사용성이나 가독성을 높이는 방법을 추천한다. 또 조건문에서 에러처리를 우선으로 하는 코드를 작성하면 훌륭한 가독성을 얻을 수 있다. 코드의 흐름을 간단히 하기 위해서는 함수를 항상 작게 관리하고 코드의 깊이가 3단까지 가는 코드를 짰을 때는 꼭 조건문을 정리하라.

※ 주석달기

주석의 중요성은 여러 번 말해도 지나침이 없지만 성의 없는 주석이나 지나치게 많은 주석은 오히러 코드의 가독성을 저해할 뿐이다. 주석을 상세하게 달 생각보다는 코드를 이해하기 쉽게 만들도록 노력하자.

(Eclipse : 언제나 다다익선이 아니라, 최선의 하나가 중요한 것 같다.)

 

※ 코드에 주석을 달기에 좋은 2가지 경우.

-         코드의 흐름을 단계별로 명시하는 주석

-         이 코드를 수정할 개발자(나나 동료)가 잊어서는 안되는 주의사항(작성자와 날짜를 명시한다.

 

 

Story 10

쉬운 그림으로 이해하기

UML이 효용성이 없다거나 새로운 방법을 전파하려는 것이 아니다. 우리는 굳이 UML을 모른다 하더라도 대부분의 개발자들이 칠판에 적혀진 네모와 동그라미, 그리고 이들을 연결하는 선만으로도 모든 것을 설명하고 또 이해할 수 있다는 점을 알고 있다. 정형화된 틀에 구애받지 않고 여려분들이 칠판으로 이야기 하면서 설명하듯 가장 쉽고 이해하기 쉬운 방법을 사용하는 것이 바람직하다고 생각한다.(필자)

 

나고수 : UML에 너무 얽매일 필요는 없다네. 중요한 것은 체계적인 문제해결이지 않은가. 실전에서는 어떤 이론도 처음의 의도대로 100% 사용되는 경우가 드물다는 것 자네도 경험으로 알고 있지 않은가? 모두 자신의 상황에 맞게 조금식 고쳐지고 보다 효과적으로 변형되기 마련이라네. 몸에도 맞지 않는 UML이란 옷을 억지로 입으려 하지 말고, 큰 장난감 가게에서 자신이 가장 재미있게 가지고 놀 수 있는 UML 장난감을 고를 수 있도록 해보게.

 

(Eclipse : 대학교 처음 입학해서 공부를 시작할 때는 마치 ‘내가 이론을 공부했으니 미리 경험했던 당신들 보다는 뛰어나오!’라는 어이없는 생각을 가지고 있었던 것 같다. 이론은 결국 사회초년생에게 경험의 부족함을 티안나게 해주는 도구임을 잘 몰랐다. 지금 생각은 이론 위의 경험 혹은 경험속의 이론만큼 강력한 것이 없다고 생각한다.)

 


Story 11

객체 생성은 객체 생성 전문가에게(팩토리 패턴(Factory Pattern))

  Ex. 삼각형, 사각형, 원형 도장

팩토리 패턴은 서로 관련성이 있거나 책임이 같은 클래스들을 생성해 주는 클래스를 객체 생성 과정 중간에 두어 복잡도를 줄이는 방법이다. 팩토리 패턴은 크게 두 부분으로 나뉜다. 먼저 팩토리 패턴이 객체를 생성하는 부분이다. 팩토리패턴을 사용하면 팩토리 클래스가 모든 객체 생성을 대신한다.

 

어떤 객체 타입을 선택했는지 파라미터로 팩토리 클래스에 넘겨주면 팩토리 클래스는 파라미터에 맞는 적당한 클래스를 new로 생성하여 넘겨준다. 이 경우 모든 리턴되는 객체의 타입은 팩토리가 알고 있는 모든 클래스의 부모클래스를 사용한다.

 

클래스 상속 트리가 책임이 명확하고 노출된 함수의 형태가 객체지향언어가 지원하는 다형성에 의해 잘 동작할 수 있을 때 팩토리 패턴은 진정한 가치를 할 수 있다. 책임도 다르고 노출된 함수 형태도 다른데 억지로 다른 팩토리로 묶는다고 효과를 볼 수 없으니 주의하자.

 

팩토리 패턴은 성격이 같은 객체를 생성할 때 구체적인 객체 타입에 다른 생성 부분을 캡슐화시켜서 코드의 복잡도를 줄여준다. 이 때 공통점 묶기를 통해 객체트리를 구성하여 팩토리 클래스가 반환할 부모 클래스를 얻을 수 있다.

 

(Eclipse : 팩토리 패턴은 이름부터 무언가 느껴지지 않는가? 공장에서 무진장 찍어내듯이 객체를 생성해내는 패턴인 것 같다. 공장에서 물건을 찍어 낼 때 기계에 몇가지 조작을 해놓으면 알아서 물건을 찍어내듯이 여러가지 상황에 맞게 객체를 생성하기 위한 패턴이라고 할 수 있다. 팩토리는 구상 클래스가 아닌 추상 클래스/인터페이스에 맞춰서 코딩할 수 있게 해주는 강력한 기법이다. 하지만 간단한 팩토리 패턴은 엄밀하게 말해서 디자인 패턴이 아니지만, 클라이언트와 구상 클래스를 분리시키기 위한 간단한 기법으로 활용할 수 있다.(Gof 디자인 패턴에는 간단한 팩토리 패턴에 대한 설명이 없더라…) 모든 팩토리 패턴에서는 어플리케이션의 구상 클래스에 대한 의존성을 줄여줌으로써 느슨한 결합을 도와주게 된다.)

 

 


Story 12

관점의 차이가 곧 객체 생성의 차이(추상 팩토리 패턴(Abstract Factory Pattern))

  Ex. 버튼, 프로그레스바, 텍스트박스

컨트롤 중심의 팩토리가 아닌 스타일 중심의 팩토리를 만드는 것이다. 각 스타일에 해당하는 컨트롤별로 버튼, 텍스트박스, 프로그래스 바가 존재하므로 각각을 생성할 수 있는 인터페이스를 작성한다. 스타일별로 팩토리를 만들었으므로 함수의 독립성을 높이기위해서는 컨트롤들을 생성할 수 있는 팩토리를 파라미터로 넣어주는 것이 유연한 방법이다.

 

관련성 있는 객체 집합을 생성하는 인터페이스를 제공하는 방법을 추상팩토리(Abstract Factory) 패턴이라고 한다. 이름에서도 알 수 있듯이 이 패턴은 팩토리의 다른 스타일이라고 볼 수 있다. 하지만 분명히 알아야할 점은 팩토리든 추상 팩토리든 공통점 묶기를 어떤 식으로 하느냐에 다라 달라진다는 점이다.

 

추상팩토리 패턴턴은 관련성을 가지는 객체의 집합을 생성하는 인터페이스를 제공하는 것이 목적이다. 팩토리를 사용하는 것도 좋지만 무분별하게 많아진다면 그 자체로도 코드의 이해도는 덜어질 수 있다. (Eclipse : Java로 객체지향을 먼저 배워서 Interface에 대한 개념을 이해하고 있었다. 덕분에 쉽게 이해할 수 있었다. 추상 팩토리 패턴과 팩토리 패턴의 가장 큰 차이점은 유연성에 있다. 아무래도 인터페이스를 이용한 추상 팩토리 패턴이 유연한 것은 당연. 추상 팩토리 패턴은 구상 클래스에 직접 의존하지 않고도 서로 관련된 객체들로 이루어진 제품군을 만들기 위한 용도로 쓰인다. 추상 팩토리 패턴에서는 객체 구성을 활용한다. 객체 생성이 팩토리 인터페이스에서 선언한 메소들로 구현되는 것이다.)

 

(Eclipse : 추상화 팩토리 패턴을 사용하기 위해서는 아무래도 구상 클래스를 추상화해서 Interface로 변형시켜야 겠한다. 아래는 Head first Design Pattern에서 발췌한 의존성 뒤집기에 대한 가이드 라인이므로 참고하길 바란다.

-         어떤 변수에도 쿠상 클래스에 대한 레퍼런스를 저장하지 말라.

(new 연산자를 사용하면 구상 클래스에 대한 레퍼런스를 사용하게 되는 것으로 팩토리를 써서 구상 클래스에 대한 레퍼런스를 변수에 저장하는 일을 미리 방지하는 것이 좋다.)

-         구상 클래스에서 유도된 클래스를 만들지 말라.

(구상클래스에서 유도된 클래스를 만들면 특정 구상 클래스에 의존하게 된다. 인터페이스나 추상 클래스처럼 추상화된 클래스로부터 클래스를 만들어야 한다.)

-         베이스 클래스에 이미 구현되어 있던 메소드를 오버라이드하지 말라.

(이미 구현되어 있는 메소드를 오버라이드한다는 것은 애초부터 베이스 클래스가 제대로 추상화 된 것이 아니었다고 볼 수 있다. 베이스 클래스에서 메소드를 정의할 때는 모든 서브클래스에서 공유할 수 있는 것만 정의해야 한다.)

이상의 내용은 그야말로 가이드라인으로 이 내용을 모두 따른다면 코딩이 불가능하지 않을까 한다. 다만 참고하여 코딩한다면 조금 더 객체지향적인 코딩을 할 수 있지 않을까?)


Story 13

필요한 것은 알아서 만들자(팩토리 메소드 패턴(Factory Method Pattern))

  Ex. 메뉴바(원형 메뉴바, 굵은 메뉴바, 원형 굵은 메뉴바, 네모 굵은 메뉴바…)

객체 생성에 대한 책임을 자식 클래스로 미루는 방법을 팩토리 메소드 패턴이라고 한다. 팩토리 메소드 패턴은 템플릿 메소드(Template Method) 패턴과 기본적으로 같은 패턴이다.

 

팩토리 메소드 패턴은 한마디로 인터페이스는 부모 클래스에서 정할 수 있지만 구체적인 객체 생성은 보다 적합한 자식 클래스에서 생성하는 것이다. 이것은 객체지향 언어가 제공하는 다형성을 활용하는 좋은 예로 결국 부모 클래스에서 공통된 인터페이스로 확장되는 클래스들을 일괄적으로 다룰 수 있는 장점을 가진다. 팩토리 메소드 패턴은 생성에 사용된다는 점만 다를 뿐 궁극적으로는 템프릿 메소드 패턴과 동일하다. 모두 ‘조금만 알기’원칙을 지킬 수 있도록 객체지향 언어가 다형성이라는 좋은 기능을 제공해주기 때문에 가능한 기능이다.

 

Ex.

(Eclipse : 간단한(일반의) 팩토리 패턴과 팩토리 매소드 패턴은 상당히 유사하지만, 간단한 팩토리 패턴은 일회용 처방에 불과한 반면, 팩토리 메소드 패턴을 이용하면 어떤 구현을 사용할지를 서브클래스에서 결정하는 프레임워크를 만들 수 있다는 결정적인 차이점이 있다. 팩토리 메소드 패턴에서는 상속을 활용한다. 객체 생성이 서브클래스에게 위임이 되는 것이다. 서브클래스에서는 팩토리 메소드를 구현하여 객체를 생산하게 되는 것이다.)


Story 14

순서를 정리하면 시점이 보인다.(템플릿 메소드 패턴(Template Method Pattern))

  Ex. 저장 -> 저장 전 + 저장 + 저장 후

  함수의 동작 방식의 구조가 부모 클래스에서 정의되고 구체적인 동작 방식은 자식 클래스에서 정의되는 형태를 템플릿 메소드(Template Method) 패턴이라고 한다. 부모 클래스에서 정의되는 함수는 순수 가상 함수여도 무방하다. 다만 순수 가상 함수일 경우에는 자식 클래스에서 반드시 재정의 해주어야만 인스턴스를 만들 수 있기 때문에 아무 일도 하지 않는 빈껍데기 함수를 부모 클래스에서 재정의 해주는 편이 개발하기 쉽다.

 

템플릿 메소드 패턴은 객체지향에서 가장 기본이 되는 패턴이다. 익숙해지면 굉장히 편한 패턴이지만 많은 개발자들이 부모 클래스에서 미리 구조를 정의한다는 말에 어려움을 느끼는 모습을 보인다. 많은 경우 부모 클래스는 분석을 통해 구조가 미리 정의되기보다도 요구사항이 점점 늘어나면서 책임이 많아지는 모습을 보인다. 관련 없는 기능들을 한 클래스에 넣는 것보다는 자식 클래스로 나누어서 클래스를 경량화할 필요가 있다.

 

상속을 통한다면 물리적으로 클래스가 나뉘기 때문에 자식 클래스에서 원하는 곳, 원하는 시점에 코드를 넣을 수 없다. 이 때 부모 클래스에서 자식 클래스들이 오버라이딩할 수 있는 함수들을 적절한 시점을 잡아서 정의해주면 부모 클래스의 수정 없이 기능을 확장할 수 있다. 이런 방법을 여러 번 거치다 보면 부모 클래스는 자연히 동작의 구조를 정의하게 되고 특화된 동작은 자식 클래스가 가지게 되는 것이다. 플래그를 남용하여 도저히 분해할 수 없는 코드를 작성하기 보다는 객체지향의 다형성을 활용하여 언제라도 다시 합칠 수 있는 코드를 만드는 것이 바람직한 방법이다.

(Eclipse : 상속의 기본적인 개념만 있다면 이건 누구나 써먹던 방식인 것 같다. 특히 MFC를 사용해봤다면 어쩔수 없이라도 사용해야 하는 아주 기본적인 패턴이 아닐까?)

 


Story 15

복잡한 조립은 전문가에게 맡기자 (빌더 패턴(Builder Pattern))

  Ex. 이미지 뷰어(굵은 테두리 이미지 박스, 카운팅 이미지박스…)

복잡한 객체를 만드는 과정만을 추출해 재사용성을 높인 클래스를 빌더(Builder)라고 한다. 빌더 패턴을 이용하면 복잡한 구성방법을 공유할 수 있다. 빌더를 구성할 때 특이한 점은 빌더는 객체의 생성과 구성에 모두 관여한다는 점이다.

 

빌더 패턴은 객체 생성 과정을 클래스화하여 객체를 동일하게 생성하는 여러 곳의 코드 중복을 막아준다. 전체 빌더 클래스의 부모클래스를 순수 가상함수로 구현하던지 가장 기본이 되는 클래스로 구현해서 활용하던지 반드시 지켜야할 룰은 없다..

 

(Eclipse : 개인적인 생각으로는 ‘빌더 패턴 =  팩토리 패턴 + 템플릿 메소드’와 같은 느낌이 든다. 내가 아직 잘 이해를 못하는 것인지, 원래 그런 것인지 아직 잘모르겠다. 이 책에 나와있는 예제만으로는 객체 생성에 대한 부분이 나와있지 않아 약간 아쉽다.)

Ex.

※ 팩토리 패턴의 경우.

※ 빌더 패턴의 경우.

Story 16

오직 하나뿐인 그대 (싱글턴 패턴(Singleton Pattern)) Ex. 프린터

싱글턴 패턴은 흔히들 시스템에 하나밖에 없는 자원을 객체의 생성과접근을 제어하기 위해 사용된다. 싱글턴 가지는 가장 큰 책임은 함부로 접근되어서는 안되는 자원을 보호하기는 것이다. 접근을 제어할 필요가 없는 자원을 싱글턴으로 작성하는 것은 쓸데 없이 객체 접근에 대한 부하만 높이는 꼴이 된다.

(Eclipse : 사실 좀 이해하기 어렵다. 객체 생성이 한곳에 이루어지는 것은 알겠는데, 객체를 누군가가 점유하고 있는 동안 못건드린 다고 하는 이야기는 잘 이해가 안간다. 객체 안쪽에서 결국 다시 Flag를 써야 하지 않을까? 뭐…객체 안에서 Flag를 쓴다면 결국 안전한 방법이긴 하겠지만…)

=>(Eclipse : 내가 잘못 이해했던 것 같다. 싱글턴 패턴 자체는 단지 유일한 객체를 생성할 수 있게 해주는 것이지 동시에 접근이 불가능하게 하는 것은 아닌 것이다. 싱글턴에서는 public을 이용한 생성자를 없애 버리므로 객체 다중생성을 한방에 막아버린다. 다만 private를 이용한 생성자 대리인을 만들어 놓고 이미 객체가 생성되었다면 객체의 생성을 허용하지 않게 된다. 하지만 이렇게 될 경우 멀티스레딩 환경에서는 정확한 작동을 하지 않을 수 있다. 따라서 getInstance()를 synchroniged 키워드를 추가해 주어야 한다.(자바의 경우.)하지만 이러한 방법보다는 애초에(멀티스레드를 생성하기 전에) 인스턴스를 먼저 생성하고 그 뒤에 사용을 하는 편이 마음이 편할 듯 하다.)

 

 

Story 17

너의 쌍둥이가 필요해 (프로토타입 패턴(Prototype Pattern)) Ex. 복사 붙여넣기, Clone

프로토타입 패턴은 객체의 원형을 기반으로 자신과 똑 같은 객체를 생성하는 방식이다. 추상 팩토리와의 결합으로도 강력한 힘을 낼 수 있다. 또 객체를 복제할 때 내부 상태(객체의 속성)를 동일하게 복제하기 때문에 현재 객체의 스냅샷(snap-shot)을 찍는데 활용할 수도 있다. new/delete 원칙 역시 Clone()함수가 객체 생성을 위한 함수임이 분명하므로 다른 모습의 new라고 볼 수 있으므로 헷갈리지 않도록 한다.

(Eclipse : 자바를 공부할 때 읽었던 소설 같은 자바에서 나왔던 Clone()에 대한 설명과 유사한 것같다.아래 내용은 Head First Design Pattern에서 발췌한 프로토타입 패턴의 장, 단점, 활용방안이다. Head First의 말로는 프로토 타입 패턴은 비교적 잘 사용되지 않는 패턴이라고 한다.)

※ 장점

 -  클라이언트에서는 새로운 인스턴스를 만드는 복잡한 과정을 몰라도 된다.

   - 클라이언트에서는 구체적인 형식을 모드더라도 객체를 생성할 수 있다.

   - 상황에 따라서 객체를 새로 생성하는 것보다 객체를 복사하는 것이 더 효율적일 수 있다.

※ 활용방안

- 시스템에서 복잡한 클래스 계층구조에 파묻혀 있는 다양한 형식의 객체 인스턴스를 새로 만들어야 하는 경우에 유용하게 써먹을 수 있다.

※ 단점

   - 때때로 객체의 복사본을 만드는 일이 매우 복잡한 경우가 있다.

Story 18

수정할 수 없는 너무 안정적인 당신 (어댑터 패턴(Adaptor Pattern))

Ex. 여러가지 암호화 지원

다른 코드의 인터페이스와 내가 원하는 인터페이스가 서로 다를 때는 인터페이스 사잉의 통신을 책임지는 클래스를 작성하는 것이 좋다. 서로 다른 인터페이스에서 중재자 역할을 해주는 클래스를 보통 어댑터(Adaptor)라고 부르며 디자인 패턴에서는 이를 어댑터 패턴이라고 부른다.

 

어댑터 패턴은 호환성을 가지지 않는 인터페이스를 맞추기 위한 목적으로 사용된다. 안정성이 확보된 코드를 DIY(Do It Yourself)정신에 입각한답시고 분해하는 순간 힘들게 얻은 안정성은 깨어지고 만다. 현실적으로 팀 개발을 할 때 다른 개발자가 작성한 코드를 내가 수정해서 붙인다면 안정성도 문제가 되지만 코드의 책임 소재가 불분명한 점도 간과할 수 없다. 꼭 어댑터 패턴을 사용하겠다는 생각보다는 문제 영역의 최소화와 안정성을 지키기 위한 마음가짐이 더 중요하다.

  

(Eclipse : 요약에 내가 적어 놓지 않았지만 저자의 야이기로는 불안정한 클래스를 사용해야 할 때 어댑터 패턴을 이용해서 불안정한 부분은 수정한다고 했는데, 내가 아직 잘 이해를 못해서인지, 불안정한 부분은 소스를 보고 그 소스에서 해결을 한 뒤에 그걸 클래스로 사용해야 한다고 생각한다. 물론 내 코드가 아니기 때문에 직접 수정해서 사용할 때 문제가 생길 수 있겠지만, 불안정한 소스를 상속받아 수정하여 쓰는 것도 문제가 생기지 않을까? 여하튼 불안정한 클래스가 문제다.)


Story 19

무슨 일이 생기면 바로 알려줘 (옵저버 패턴(Opserver Pattern))

Ex. 여러 가지의 다운로드 속도창 보여주기

정보의 변화에 관심이 있는 객체들(옵저버)는 그들의 목록을 가지고 있는 객체(서브젝트)가 소유하는 정보의 변화에 관심을 가지며 변화가 있어났을 경우 자신에게 알려주기를 바란다. 이처럼 서브젝트가 옵저버들이 알고싶어하는 정보의 변화가 있을 때 그 변화를 옵저버에게 알려주는 패턴을 ‘옵저버 패턴’이라고 한다.

 

서브젝트는 옵저버들의 목록을 가지고 있어야 한다. 서브젝트가 소유하는 옵저버 목록은 옵저버들의 의지에 따라 추가/삭제 될 수 있다. 쉽게 설명하면 정보의 변화를 알고 싶다면 등록하고 정보 변화에 관심이 없다면 등록을 제거하는 형태를 가진다. 이와 같은 모습 때문에 옵저버 패턴은 Publish(발행자)-Subscribe(구독자) 관계를 형성하기도 한다.

 

옵저버 패턴은 정보 객체가 변경되었을 때 이 정보 객체를 참조하는 다른 객체들에게 변경사항을 알리어변경된 정보를 즉각적으로 반영할 수 있는 방법이다. 이 때 정보 객체를 소유하는 쪽을 서브젝트(Subject)라고 하며 정보 객체를 참조하는 객체를 옵저버(Observer)라고 부른다. 서브젝트와 옵저버는 1대 n의 관계를 가진다.

(Eclipse : MFC를 사용하다보면 많이 쓰게되는 패턴인 것 같다. 메시지를 주고 받는 것이 마치 옵저버와 서브젝트의 관계를 보는 것과 같다고 생각된다. 메시지를 요구하는 것이 아니라, 바뀌어야 할 때 전달 받는다는 것이 관건인 것 같다.)

 

 


Story 20

한가지 탐색법만 기억하라 (이터레이터 패턴(Iterator Pattern))

  Ex. 여러가지 자료구조의 탐색 방법의 지원

이터레이터 패턴은 컬랙션의 내부 구현과 탐색 방법을 분리시키는 방법이다. 이터레이터 패턴은 탐색하는 행위를 하나의 책임으로 보고 패턴화 했다는데 의의를 가진다. 이 패턴 구현의 가장 중요한 요소는 커서이다. 커서가 컬렉션의 시작과 끝의 범위 안에서 정확히 동작해야 안전한 구현이 가능하다. 멀티스레드 황경에서는 커서의 범위가 수시로 간섭 당할 수 있으므로 탐색 전에 범위의 간섭이 일어나지 않도록 해야 한다.

탐색 외에 추가, 삭제 같이 다른 액션이 필요하다면 이터레이션 패턴은 적합하지 않음을 명시해야 한다.(Eclipse : 또한 다중접근이 가능한 멀티쓰레드 코드를 디자인 할 경우 좀 더 조심해야 한다.)

(Eclipse : 솔직히 잘 이해가 안가는 부분이 많습니다. 그냥 STL을 쓰면 되는게 아닌지…)

->(Eclipse : 뭔가 잘못 이해했던 것 같다. 컬랙션에 들어있는 모든 객체체에게 일일이 접근하는 작업을 할 때 어떤 식으로 저장했는지 전부 보여줘야 할 것이 아니라, 객체를 저장하는 방식은 보여주지 않으면서도 클라이언트로 하여금 객체들에게 일일이 접근할 수 있게 해줄 방법을 찾아야 할 것이다. 이러한 상황에서 이터레이터 패턴을 활용하면 문제를 해결 할 수 있게된다. 또 여러가지의 자료구조를 사용할 경우에도 각각에 맞는 자료구조를 따로 제공할 것이 아니라 하나의 인터페이스로 사용하는 모든 자료구조를 쉽게 접근할 수 있게 해주는 것이 바람직한 이터레이터의 기본 모델이다.)

(Eclipse : 자바에서는 기본적으로 이터레이터 인터페이스를 제공하고 있다고 한다.)

 


Story 21

복합구조도 접근법은 하나(컴포지트 패턴(Composite Pattern))

Ex. 폴더, 파일 트리(폴더와 파일의 공통점을 이용해서 트리를 구성한다.), 메뉴디자인

연속적인 복합 구조에서 객체의 위치나 객체의 종류에 상관없이 모든 객체를 동일하게 다루고 연쇄반응을 가질 수 있도록 하는 방법을 컴포지트 패턴이라고 한다. 컴포지트 패턴은 재귀적 합성을 사용한다. 재귀적 합성이란 컨테이너 클래스가 다른 컨테이너 클래스를 가질 수 있는 방법을 의미한다.

 

컴포지트 패턴을 사용하기 위해서는 사용할 컨테이너 클래스의 공통점을 묶어 인터페이스를 만드는 것이 관건이다. 공통점 묶기가 어려울 경우 좀더 일반적인 시각에서 접근하여 공통점을 묶는 것이 좋다.

 

컴포지트 패턴은 객체들의 트리로 대변되는 객체들 사이의 소유구조를 동일한 인터페이스로 다룰 수 있는 방법이다. 개별 객체와 복합 객체를 코드상에서따로 구분하지 않고 이들의 공통점으로 만들어진 인터페이스를 구성하는 것이 이 패턴의 핵심이다. 개별 객체는 자식을 가지지 않는 복합구조로 이해하면 보다 쉽게 인터페이스를 구성할 수 있다.

 

(Eclipse : 컴포지트 패턴은 내가 볼땐 재귀함수 + 객체지향(공통점 묶기)이라고 생각된다. 누가 뭐라고 해도 컴포지트 패턴의 가장 핵심은 다른 객체들의 공통점을 찾아내어 이를 반복구조로 만들어 내는 것이다. 거의 모든 디자인 패턴의 주요 쟁점들과 마찬가지로 컴포지트 패턴 또한 결국 공통점 묶기에서 생각을 시작한다고 볼 수 있다.)

 

(Eclipse : 컴포지트 패턴에서는 단일 역할 원칙을 깨면서 대신에 투명성을 확보하기 위한 패턴이라고 할 수 있다. 여기서 “투명성”이란 컴포턴트 인터페이스에 자식들을 관리하기 위한 기능과 잎(leaf node)으로써의 기능을 전부 집어넣음으로써 클라이언트에서 복합 객체와 잎 노드의 똑 같은 방식으로 처리할 수 있도록 할 수 있다. 어떤 원소가 복합 객체인지 입 노드인지가 클라이언트에게는 투명하게 느껴지는 것이다.)


Story 22

난 기분에 따라 행동이 달라져(스테이트 패턴(State Pattern))

  Ex. 뽑기 자판기.

각 상태마다 동작하는 방식이 다르고 책임이 다르면 상태만 클래스화 해서 상태머신을 만들 수 있다. 이런 방식을 스테이트 패턴이라고 한다.

 

스테이트 패턴을 구성하기 위해서는 두 가지 개념이 필요하다. 먼저 상태를 의미하는 스테이트이다. 상태는 지하철 개찰구의 예에서 대기, 확인, 통과의 각 세부 상태를 의한다. 다음으로 이런 상태를 내부적으로 가지는(언어적으로는 멤버 변수로 가지고 있는) 컨텍스트(Context)이다. 컨텍스트는 지하철 개찰구의 예에서 지하철 개찰구에 해당한다. 즉 유저(클라이언트 코드)와 직접적으로 만나는 부분이고 유저는 이 컨텍스트와 통신한다.

 

※ 상태머신의 복함성을 낮추는 특성

-         현재상태는 오직 하나만 존재한다.

-         현재 상태에서 입력 조건에 따라 변화될 다음 상태만을 알면 된다.

 

(Eclipse : 정말 궁금했던 부분인데, 안타깝게도 이해가 안된다. 플래그를 안쓰기위해서 클래스를 만들고, 인터페이스를 만들지만 결국 그 안에서 플래그를 사용한다. 말로는 이렇게 하면 안꼬인다고 하지만, 잘 이해가 안간다. 너무 생소한 개념이라 그런 것인지…. 몇시간동안 씨름했지만…결국 다른 책을 봐야할 것 같다.)

 

-> (Eclipse : Head First Designe Pattern을 읽으면서 이해할 수 있었다. 스테이트 패턴의 핵심은 스테이트에 따른 클래스를 생성하여 해당 클래스에서 각 스테이트에 따른 행동을 취해주는 것이다. 스테이트 클래스를 만들경우 인터페이스를 생성하여 각 스테이트의 변경을 쉽게 해야 한다.)


Story 23

골라쓰는 알고리즘(스트래티지(정책) 패턴(Strategy Pattern))

  Ex. 다양한(본문검색, 제목검색, 저자검색… ) 검색의 지원

독립적으로 확장 가능한 다양한 알고리즘이 존재할 경우 각각의 방법을 클래스로 캡슐화 하여 선택적으로 교체가 가능하도록 하는 방법을 스트래티지 패턴이라고 한다. 모든 알고르짐이 동일한 인터페이스를 가지므로 알고리즘을 사용하는 클라이언트 코드에서는 알고리즘을 쉽게 교체할 수 있다. 즉, 클라이언트는 알고리즘의 확장과 변화에 종속적이지 않게 된다.(단, 파라미터가 많아진다는 점은 분명 스트래티지 패턴의 약점이다.)

(Eclipse : 파라미터가 굉장히 무거워진다면 그냥 템플릿 메소드 패턴을 이용하는 편이 마음이 편하겠다.)

 

스트래티지 패턴은 알고리즘을 독립적으로 확장시킬 수 있는 방법이다. 동일한 인터페이스로 확장된 알고리즘은 클래스의 멤버 함수로 속해 있을 때보다 더 높은 확장성을 가진다. 스트래티지 패턴을 사용하면 무거운 객체를 상속하지 않고 확장의 범위를 최소화 할 수 있다.

 

(Eclisep : 이 챕터를 보면서 느낀건 역시 상황에 맞는 패턴이 중요하겠다는 것이다. 부모클래스가 상당히 무거운 상황에서 굳이 부모 클래스를 엎고 가는 것이 아니라 새로운 인터페이스를 만들어서 그 길을 우회할 수도 있다는 것을 보여준다. 디자인 패턴이라는 것이 상당히 어렵기도 하지만, 역시 재미있는 부분인 것 같다는 생각을 만들어주는 챕터였다.)


Story 24

공유되는 정보와 대리인(프록시 패턴(Proxy Pattern), 플라이 웨이트 패턴(Flyweight Pattern)

  Ex. 클립아트

프록시 패턴은 복잡도가 증가할 때 하나의 프록시를 마치 메니저처럼 운영하여 객체간 복잡도를 줄여주는 역할을 한다.(프록시는 주로 복잡한 과정을 내부적으로 캡슐화해서 처리한다. 프록시는 일종의 대리인이라고 볼 수 있다. 마치 클라이언트 서버로부터 서비스를 받는 다는 느낌의 것이다.) 프록시 패턴은 클라이언트 코드에서 사용을 원하는 객체로의 접근을 제어하기 위한 목적으로 사용된다. 프록시는 내부적으로 자신이 ‘제어’하는 객체와 동일한 인터페이스를 클라이언트에게 제공하여 클라이언트가 통신을 원하는 객체와 직접적으로 통신을 하는 것처럼 믿게 만든다.

 

플라이웨이트 패턴은 대량 생성될 수 있는 객체들 사이에서 중복되는 정보를 공유하는 방법이다. 공통점을 묶을 때는 ‘객체마다 변하기 때문에 따로 가져야 하는 부가 정보’와 ‘변하지 않기 때문에 공유할 수 있는 공유 정보’를 잘 구분하여야 한다. 플라이웨이트 패턴은 패턴에 따른 정해진 코드 모양을 따르는 것이 중요한 것이 아니라 공유 정보와 공유되지 않는 부가 정보를 잘 구부하는 것이 핵심이다. 플라이트웨이트 패턴은 구조 중심의 패턴이 아닌 효율성 중심의 패턴이다. 효율성은 문제 상황에 따라 천차만별이므로 어디서나 통용되는 코드를 제시하기 무척 어렵다. 하지만 플라이웨이트 패턴이 당당히 독립된 패턴으로 제공된다는 것은 달리 말하면 구조적인 디자인 패턴을 사용하더라도 비용에 대해 항상 고려해야 한다는 것을 의미한다. 중복되는 정보를 공유하는 것만으로도 많은 비용을 절감할 수 있다.

 

플라이웨이트 패턴은 대량으로 생성되는 객체들 사이의 중복되는 정보를 공유, 메모리적인 효율성을 높이는 방법이다. 중복된 정보를 공유하는 방법은 싱글턴, 팩터리, 자원 풀(Resource Pool)등 여러방법으로 구현될 수 있다. 하지만 가장 중요한 것은 어떤 정보를 공유시키고 어떤 정보를 부가적인 정보로 따로 가져갈 것인지에 대한 분석을 하는 것이다.

 

(Eclipse : 사실 디자인 패턴은 논리적인 구조에만 포커스를 맞추고 있다고 생각했다. 하지만 플라이웨이트 패턴은 그 생각을 무참히 깨주는 패턴이다. 하지만 이런 패턴은 내 생각에 GoF형님들이 책에 넣지 않았어도 많은 프로그래머들이 항상 고심하는 부분이 아닐까 한다. 대부분의 자긍심을 가지는 프로그래머라면 자신이 만든 프로그램에 대한 퍼포먼스와 메모리에 대해 한번쯤 생각하고 있을 테니 말이다. 하지만 이렇게 한번 더 집고 넘어가니 다시 한번 메모리와 퍼포먼스를 생각해볼 기회가 되었던 것 같다.)

 

 


Story 25

행동만 따로 떼어보자(커맨드 패턴(Command Pattern))

기능동작을 별도의 객체군으로 추상화시켜 확장성 있게 사용하는 방법을 커맨드 패턴이라고 한다. 커맨드 패턴은 객체의 행동을 별도의 클래스에 캡슐화해서 행동 객체에 확장성을 부여한다. 각각의 커맨드들은 특정 객체에 의존하지 않도록 만들어지므로 재활용성이 매우 높다.(Ex. 자바의 UI 이벤트 처리모델)

 

(Eclipse : 내가 커맨드 패턴을 보고 느낀건 그냥 일반적인 템플릿 메소드 패턴이었다. 잘못 이해한 것일 수도 있고, 유사한 패턴일 수도 있겠다. 하지만 아무래도 두 패턴 모두의 목적은 공통점은 묶고, 좀더 구조적으로 코딩하자는 것이겠지..)

 

 

Story 26

꾸미는 방법도 여러가지(데코레이터 패턴(Decorator Pattern))

기능을 상속이 아닌 동적 결합으로 추가하는 방법을 데코레이터 패턴이라고 한다. 테코레이터는 원본 객체를 입력받아 원본 객체처럼 행동하면서 원본 객체의 기능을 동적으로 확장한다. 데코레이터 패턴은 입력받는 객체군 전체에 동적으로 기능을 추가할 수 있으므로 상속보다 유연한 방법이다.

 

데코레이터 패턴은 기본 기능을 하는 객체와 이 객체를 기반으로 동작하는 데코레이터들을 조합하여 기능을 확장하는 방법이다. 데코레이터 패턴은 상속보다 유연한 방법으로 동적으로 기능을 추가/삭제 할 수 있고 조합해서 쓸 수 있다는 장점이 있다. JAVA의 I/O모델은 데코레이터 패턴을 사용한 대표적인 사례이다.

 

(Eclipse : 자바를 사용하면 누구나 데코레이터 패턴을 사용하게 된다. 하지만 나는 그게 여태 데코레이터 패턴인줄 모르고 사용했다. 파일입출력, 문자열 스트림, 그리고 UI개발등 많은 부분에서 데코레이터 패턴을 사용한다. 하지만, 이상하게도 C++를 하면서 데코레이터 패턴을 본 적은 없다. 컴파일러가 지원을 안하는 것인지..(그건 아닐 것 같은데… 실험을 해보면 답은 나오겠지만…) 어째서인지 C++코딩을 하면서 한번도 본적이 없는 것 같다.)


신고

'programing > ETC' 카테고리의 다른 글

인코딩  (0) 2009.08.14
정규식  (0) 2009.08.12
mylyn, trac 플러그인 설치  (0) 2009.08.12
Subversion 설치 방법 ~ SVN~~  (0) 2009.08.12
이클립스에서 탭을 공백으로 처리하기  (0) 2009.08.12
패턴 1  (0) 2009.04.14
Posted by 대절님

댓글을 달아 주세요



티스토리 툴바