본문 바로가기

Application

GoF 디자인 패턴

GoF 디자인 패턴

1. GoF 디자인 패턴 종류


구분 

종류 

생성 패턴 

Singleton, Abstract Factory, Factory Method, Builder, Prototype 

구조 패턴 

Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy 

행위 패턴 

Command, Interpreter, Iterator, Mediator, Template Method, Visitor, State, Strategy, Observer, Chain of Responsibility, Memento 

 



2. 생성 패턴


- 객체를 생성하고 참조하는 과정을 추상화하여 시스템이 객체의 생성과 조합들에 구애 받지 않고 개발될 수 있도록 도와준다.


- 특정객체가 생성되고 변경되어도 전체 시스템의 변화는 최소화가 되도록 만들어 주어, 시스템의 확장이나 유지보수 시 최소 비용만 소요된다.


(1) Sigleton


- 객체를 하나만 생성해서 이용하는 패턴


- 어떤 클래스의 인스턴스는 오직 하나임을 보장함


- Singleton s = new Singleton();


- Singleton s = Singlton.getInstance(); (Private 생성자를 이용해 강제한다)



(2) Factory Method


- Factory Method 패턴과 Abstract Factory 패턴의 기본이 되는 패턴


- Factory 패턴의 기본 모양에서 객체 생성을 Factory 클래스의 하위 클래스에서 처리하도록 하는 패턴


- 생성하려는 객체의 클래스를 정확히 지정하지 않으면서 객체를 만드는 또 다른 메소드를 정의하여 처리


- 추상메소드 getConnection()을 가진다.


- 하위 자식 클래스 TCPCOnnectionFactory, UDPConnectionFactory, HTTPConnection Factory에서 getConnection() 메소드를 각각에 알맞게 구현한다.



(3) Abstract Factory


- Factory 클래스를 추상으로 제공


- Factory Method 패턴이 공장라인의 부품을 교체할 때 유용한 것이라면 Abstract Factory 패턴은 공장라인 자체를 교체하는 것에 유용하다.


- 다양한 구성 요소 별로 객체의 집합을 생성해야 할 때 유용하다.


- 예)

Robot homeRobot = new Robot();

RobotFactory homeFactory = new HomeRobotFactory();

homeRobot.addHead(homeFactory.createHead());

.

.

homeRobot.displayRobot();  // 전체 로봇을 출력한다.




(4)  Builder


- 객체 생성 작업을 대신해줄 클래스를 추가하는 패턴


- 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴


- 객체 생성이 복잡하거나 여러 개의 추가 작업이 필요한 경우 유용함


- 예)

Director director = new Director(new HTMLBuilder(), "member.html");

director.construct();

director.makeFile();


(5) Prototype


- 복제 패턴, clone() 메소드 이용


- 생성할 객체들의 타입이 프로토타입인 인스턴스로부터 결정되는 패턴


- 프로토타입인 인스턴스는 새로운 객체를 만들기 위해 클론(clone) 됨


- 주의

① : Object의 done() 메소드는 protected로, 상속 후 재정의가 필요함

② : Cloneable 인터페이스 구현이 필요함 (그렇지 않으면 CloneNotSupportedException 발생)


3. 구조 패턴


- 복잡한 구조를 이루는 클래스들을 어떻게 개발하기에도 쉽고 보기에도 좋은 형태를 만들 것인가에 대한 답을 제시


- 구조 패턴을 이용해서 시스템을 구축하면 새로운 기능을 가진 복합객체를 효과적으로 작성할 수 있다.


(1) Adapter


- 위임을 이용한 방식


> Book은 Arraylist에 담는 것이 좋을까, BookStore에 담는 것이 좋을까?



- 상속을 이용한 방식 (주의)


① 이미 다른 클래스를 상속 받았다면 사용할 수 없다.

② LSP에 따라 분명히 상속 관계인 경우에만 사용해야 한다.

③ 상속이 강한 결합의 형태로 잘못 작성된 경우 수정이 불가능한 상황이 발생할 수 있다.

(예 : Vector 클래스를 상속 받은 Stack 클래스)



(2) Bridge


- 구현부에서 추상층을 분리하여 각자 독립적으로 변형할 수 있게 하는 패턴


- 기능 클래스 계층과 구현 클래스 계층을 연결하는 다리


- 기능 클래스 계층 : MultiWrite에 print(int) 기능이 추가되었다.


- 구현 클래스 계층 : FileWriteImpl 을 통해 구현되었다.


- 예)

MultiWriter mw = new MultiWriter(new FileWriteImpl("test.txt", "test success");



(3) Composite


- 객체들의 관계를 트리 구조로 구성하여 부분-전체 계층을 표현하는 패턴(복합패턴)


- 재귀적 구조, 파일디렉토리 탐색기 구조


- 예)

Department d1 = new Department("전체부서");

Department d2 = new Department("개발부");

d1.add(d2);


Employee e1 = new Employee("김주혁");

Employee e2 = new Employee("김고흔");


d2.add(e1);

d2.add(e2);


d1.print(); // 한 번에 전체보기




(4) Decorator


- 주어진 상황 및 용도에 따라 어떤 객체에 책임을 덧붙이는 패턴


- 장식대상이 되는 클래스와 장식 클래스를 구분해야 함.


- 예)

StarWindow sw = new StarWindow(10.5);

sw.draw();


VerticalSharpWindow hsw = new VerticalSharpWindow(sw);

hsw.draw(); // 장식 대상(sw), 장식 (hsw)


- 예2)

BifferedReader br = new BifferedReader(new InputStream Reader(System.in));



(5) Facade


- 클래스 라이브러리 같은 어떤 SW의 다른 커다란 코드 부분에 대한 간략화 된 인터페이스를 제공하는 객체 이용 패턴


- 높은 레벨의 간략한 인터페이스 제공


- 예)

UseFileMaker maker = new UseFileMaker();

maker.makeUseFile("usefile.txt");


UseFileMaker 클래스의 makeUsefile 메소드만 호출하여 전체 업무를 처리한다.




(6) Flyweight


- 가능한 많은 데이터를 서로 공유하여 사용하도록 하여 메모리 사용량을 최소화하는 패턴


- 가능한 new를 통한 객체 생성을 줄여 메모리를 적게 차지하고 객체를 메모리에 올리기 위한 오버헤드를 줄인다.



(7) Proxy


- 본인 객체 대신 대리인 객체가 어느 정도 일을 처리해 주는 대리인 패턴


- AddressBookProxy가 작업을 가져가고 일부 FileLoader를 이용하는 작업만 AddressBookImpl이 수행한다.


- 예)

AddressBookProxy proxy = new AddressBookProxy("data.ser");

proxy.add(new AddressImpl("Apple inc.", "1Infinite Loop", "Redwood City", "CA", "93741"));

ArrayList addresses = proxy.getAllAddresses();



3. 행위 패턴


- 객체들간에 행위나 알고리즘 등과 관련된 패턴


- 응용 분야에 따라 행위가 다른 객체로 옮겨가거나 알고리즘이 대체되는 경우에 많은 도움을 주는 패턴이다.


(1) Command


- 메소드 호출을 명령으로 생각하고 명령을 모아서 관리하는 명령 패턴


- 명령의 집합을 보존해두면 똑같은 명령을 재실행할 수 있고, 여러 개의 명령을 모은 것을 새로운 명령으로 재사용할 수 있다.


- 요청을 객체의 형태로 캡슐화하여 서로 요청이 다른 사용자의 매개변수와 요청 저장 또는 로깅, 그리고 연산의 취소를 지원하게 만든다.



(2) Iterator


- 몇 개인지 몰라도 무엇인가 많이 모여있는 것 중에서 하나씩 끄집어 내어 열거하면서 전체를 검색하는 반복 패턴


- 일반적으로 hasNext() 메소드를 통해 다음이 존재하는지 확인하고 next() 메소드를 통해 다음 항목을 하나씩 끄집어 낼 수 있다.


- JDK 1.2 버전부터 추가된 Collection Framework 자료구조는 Iterator 패턴 사용


(3) Mediator


- 각 클래스가 분산되어 있는 경우 조정자 혹은 중개자를 두어 처리의 효율성을 높일 수 있는 중재자 패턴


- 예)

Mediator 가 BtnView, BtnSearch, BtnBook 클래스를 중재한다.

Mediator 클래스는 각 멤버들과 Association 관계에 있다.




(4) Template Method


- 상위 클래스에 템플릿을 정해 놓고 하위 클래스에서 구체적인 내용을 결정하는 패턴


- 템플릿을 만들어 프로세스를 강조하고 싶은 경우 사용한다.


- 프로세스를 강제하는 메소드를 템플릿메소드라고 부른다.


- 예) Check 프로세스를 아래와 같이 정의함


public void check(){

checkBank();

checkCredit();

checkLoan();

checkStock();

checkIncome();

}




(5) Visitor


- 방문자 패턴


- 데이터 구조와 처리를 분리하여 데이터 구조 안을 돌아다니는 방문자 클래스에게 처리를 맡기는 패턴


- 새로운 처리 기능이 필요한 경우 해당 방문자를 만든다.


- 예)

public void accept(Vistor v){

v.visit(this);

}



(6) State


- 객체가 아닌 상태를 클래스로 표현하는 상태 패턴


- Accounting 상태, Sales 상태, Management 상태, 각 상태별로 open/close/log 메소드가 다르게 동작한다.


(7) Strategy


- 알고리즘으로 구현될 부분을 교체 가능하도록 처리하는 전략패턴, 알고리즘 패턴


- 시스템 속에 다양한 전술(알고리즘)이 동일한 객체 속에 존재하도록 만들고 상황에 따라 필요한 전술이 사용되도록 한다.


- 예)

컴퓨터와 바둑 게임 시 초보자/중수/고수라는 전략 알고리즘을 구현한 객체를 따로 만들어 놓고, 상황에 따라 다르게 실행할 수 있다.



(8) Observer


- 관찰 대상의 상태가 변경되면 관찰자에게 통지되는 관찰자 패턴


- 실제적으로 관찰 대상으로부터 변화가 생기면 통지를 기다리는 역할을 수행 (publish-subscribe : 발행-구독)

- 특정 데이터나 객체를 감시하고 있다가 변화가 발생 했을 때, 시스템에 이를 알리고 연관된 객체들이 적절한 작업을 동일한 인터페이스를 이용하여 실행하도록 만든다.


- 예)

JDK에서 java.util.Observer / java.util.Observable 두 가지를 제공하지만 이미 다른 클래스를 상속 받고 있을 경우, 하위 클래스로 만들기 어렵기 때문에 직접 Observer 패턴을 구현하는 것이 좋음



(8) Chain of Responsibility


- 각자 객체가 자신이 맡은 책임을 완수하여 전체적인 요구를 수용할 수 있게 하는 책임연쇄 패턴


- 사용자가 원하는 작업을 어떤 객체에게 시킬지 모를 때, 그냥 작업을 객체들의 집합에 던져 버리면 되도록 만드는 패턴


- 예)

Manager : 10 * Base

Director : 20 * Base

VicePresident : 40 * Base

President : 60 * Base


Manager가 감당할 수 없는 일인 경우 Director에게 넘긴다.


(9) Memento


- 이전 행위를 Memento 클래스의 객체로 생성하여 undo list에 보존하는 보존과 복원 패턴


- 시스템이 이전에 수행했던 작업을 기억하고 이전의 작업으로 복귀를 해야 하는 구조를 가져야 할 때 유용하게 사용할 수 있는 패턴


- Memento 패턴을 이용하면 Undo, Redo, Snapshot 등을 실행할 수 있다.


- 예)

undo List에 등록한다.

previous() 메소드를 통해 이전 정보를 찾을 수 있다.


(10) Interpreter


- 인터프리팅을 위한 패턴


- 새로운 스크립트 언어를 위한 패턴으로 엑셀 스크립트를 통해 엑셀의 변경 없이 엑셀에 새로운 기능을 수행 할 수 있다.


- 예) 간단한 미니 언어 작성하기 (EBNF 표기법)

<command List> ::=<comand>*end

<command> ::=<repeat comman> | <primitive comman>

<primitive command> ::= go | right | left

<program> ::= repeat<number><command list>