Design Pattern Flashcards
디자인 패턴
▣ 정의 - 반복적으로 일어나는 문제들을 설명하고, 그 문제들에 대한 해법의 핵심을 설명하는 경험적 패턴 ▣ 요소 (이문해결) - 이름 : 문제와 해법을 서술 - 문제 : 문제와 배경 - 해법 : 관계, 책임 설명 - 결과 : 결과와 장단점 ▣ 원칙 - 바뀌는 부분은 캡슐화 - 상속보다는 위임 - 구현이 아닌 인터페이스에 맞게 - 가능하면 느슨하게 결합 - SOLID ▣ 분류 - 객체생성 패턴 - 구조개선 패턴 - 행위개선 패턴 ▣ 23개의 디자인 패턴(팩앱빌프싱 앱브컴데파플프 인템체커이메메옵스스비) 1) 생성 - Factory Method : 인스턴스화될 객체의 서브클래스 - Abstract Factory : 제품객체군 - Builder : 복합 객체 생성 - Prototype : 인스턴스화될 객체 클래스 - Singleton : 인스턴스가 하나일 때 2) 구조 - Adaptor : 상속 - Adaptor : 위임 - Bridge : 객체 구현 - Composite : 객체의 합성과 구조 - Decorator : 서브클래싱 없이 객체의 책임성 - Facade : 서브시스템에 대한 인터페이스 - Flyweight : 객체 저장 비용 - Proxy : 객체 접근방법 3) 행위 - Interpreter : 언어의 문법과 해석방법 - Template Method : 알고리즘 단계 - Chain of Responsibility : 요청처리 객체 - Command : 요청 처리 시점과 방법 - Iterator : 집합객체 요소 접근/순회방법 - Mediator : 객체 상호 작용 - Memento : 객체 상호 작용 - Observer : 종속객체 상태 변경 - State : 객체 상태 - Strategy : 알고리즘 - Visitor : 클래스변경없이 객체에 적용할 수 있는 오퍼레이션
Abstract Factory
▣ 정의 - 클라이언트에서 구상 클래스를 지정하지 않으면서도 일군의 객체를 생성할 수 있도록 하는 패턴 ▣ 활용 - 시스템을 독립적으로 만들고자 할 때 - 한번 구성한 제품을 다른 것으로 대체 가능 할 때 - 제품이 갖는 제약사항을 따라야 할 때 ▣ 결과 - 추상 인터페이스를 통해서만 클라이언트 프로그램 작성 - 쉬운 제품군 대체 - 제품간의 일관성 증진 ▣ 참여객체 - AbstractFactory : 개념적 공장 - ConcreteFactory : 구체적 공장 - AbstractProduct : 개념적 제품 - ConcreteProduct : 구체적 제품 - Client
Factory Method
▣ 정의 - 생성할 구상 클래스를 서브 클래스에서 결정 ▣ 활용 - 생성할 객체 타입을 예측할 수 없을 때 - 객체 생성의 책임을 서브클래스에 위임시키고 서브클래스에 대한 정보를 은닉하고자 할 때 ▣ 결과 - 애플리케이션에 국한된 클래스가 코드에 종속될 필요를 제거 - 서브클래스에 대한 Hook 메소드 제공 (객체별 다른 기능 제공) ▣ 참여객체 - Product(I/F) : 객체의 인터페이스 정의 - ConcreteProduct : Product 인터페이스 구현 - Creator(A) : 팩토리 메소드 선언 (Product 타입 객체 변환) - ConcreteCreator : 팩토리 메소드 재정의
Builder
▣ 정의
- 제품을 여러 단계로 나눠서 만들 수 있도록 제품 생산 단계를 캡슐화
▣ 활용
- 합성할 객체들의 표현이 서로 다르더라도 구축 공정이 이를 지원해야 할 때
▣ 결과
- 제품에 대한 내부 표현을 다양하게 변화
- 생성과 표현에 필요한 코드 분리
- 복합 객체 생성 공정 세밀화
▣ 참여객체
- Builder(I/F) : I/F API 결정, 인스턴스의 각 부분을 만들기 위한 메소드 준비
- ConcreteBuilder(C)(Dependency Product) : I/F API 구현, 인스턴스의 각 부분을 만드는 부분, 조립하는 부분, 최종적으로 인스턴스를 생성하는 부분을 모두 구현
- Director(C)(Aggregation Builder) : I/F API 사용, 원하는 부품 조립 후 인스턴스 생성
Product : Builder에 의해 최종적으로 생산된 제품
Prototype
▣ 정의
- 클래스로 부터 인스턴스를 만드는 것이 아니라 인스턴스를 복사해서 새로운 인스턴스 생성 (Clone())
▣ 활용
- 어떤 클래스의 인스턴스를 만드는 것이 자원/시간을 많이 소모하거나, 복잡한 경우 사용
- 종류가 너무 많아 한 개의 클래스로 할 수 없는 경우
▣ 결과
- 클라이언트에서는 새로운 인스턴스를 만드는 복잡한 과정을 몰라도 된다.
- 상황에 따라 객체를 생성하는 것보다 복사하는 것이 더 효율적
- 런타임에 새로운 제품을 삽입하고 삭제 가능
- 객체에 정의된 변수 값에 따라 행위 변경
- 서브 클래스의 수 감소
▣ 참여객체
- Prototype(I/F) : 자신을 복제하는데 필요한 인터페이스를 정의
- ConcretePrototype : 자신을 복제하는 오퍼레이션을 구현
- Client : Prototype에 복제를 요청하여 새로운 객체를 생성
Singleton
▣ 정의
- 지정한 클래스의 인스턴스가 반드시 1개만 존재하도록 하는 패턴
▣ 활용
- 유일하게 존재하는 인스턴스가 상속에 의해 확장되어야 할 때
- 클라이언트가 코드 수정없이 확장된 서브클래스의 인스턴스를 사용할 수 있어야 할 때
▣ 결과
- 변수영역 감소 (전역변수를 정의해 발생하는 디버깅의 어려움 제거)
- 인스턴스 개수 변경 용이 (인스턴스 접근 허용 범위 제어)
▣ 참여객체
- static uniqueInstance
- singletonDate
+ static Instance()
+ Operation()
▣ 만드는 방법 (이스래 쓰인 이더)
- Eager Initialization : getInstance()
- Static Block Initialization : static 초기화블럭이용, 클래스 로딩시 최초 한번만 실행, 로직 추가 가능, 에러처리 가능
- Lazy Initialization : getInstance() 에서 null 인 경우만 생성, Multi Thread 방식의 경우 불안전
- Thread safe Initialization : synchronized 사용, 여러 thread 들이 동시에 접근해서 인스턴스를 생성시키는 위험 제거, 수 많은 thread들이 getInstance() 호출로 성능저하 발생
- Initialization on demand holder idiom : jvm의 class loader의 매커니즘과 class의 load 시점을 이용하여 내부에 class를 생성시킴으로써 thread 간의 동기화 문제 해결
- enum Initialization : Instance가 생성될 때, multi thread 로 부터 안전, 단 한번의 인스턴스 생성 보장
- Double Checking Locking : volatile static, synchronized (singleton.class), 인스턴스의 생성여부를 확인 후, 미생성시에만 동기화 수행
Adaptor
▣ 정의 - 이미 제공하는 것과 필요한 것 사이의 간격을 매우는 패턴 - 클래스에 의한 Adaptor (상속) - 인스턴스에 의한 Adaptor (위임) ▣ 활용 - 기존 클래스를 사용해야 하나 인터페이스가 수정되어야 하는 경우 - 이미 만들어진 것을 재사용해야 하나, 재사용 가능한 라이브러리를 수정할 수 없는 경우 ▣ 결과 - 클래스 Adaptor : Adaptee에 정의된 행위 재정의 가능 - 객체 Adaptor : Adaptee에 정의된 행위 재정의 어려움 ▣ 참여객체 - Client : 어떠한 행위가 필요한 객체 (직류 12볼트 노트북) - Target(상속) : Client에 필요한 메소드 제공 (직류 12볼트) - Adaptee(위임) : 기존 메소드 가지고 있음 (교류 120볼트) - Adapter : Adaptee의 메소드 활용, Target이 필요로 하는 메소드 만듦 (교류 120볼트를 직류 12볼트로 바꿔주는 어댑터
Bridge
▣ 정의
- 기능의 클래스 계층과 구현의 클래스 계층을 분리하는 패턴
▣ 활용
- 추상화 개념과 이에 대한 구현간의 종속성을 없애고 싶거나, 또는 런타임시 구현 방법을 선택하거나 구현 내용을 변경하고 싶은 경우
▣ 결과
- 인터페이스와 구현의 결합도 약화
- 확장성 제고 (abstraction 과 implementor를 독립적으로 확장)
▣ 참여객체
- Abstraction(A)(Aggregation Implementator) : 기능 클래스 계층의 취상위 클래스 (Display)
- RefineAbstraction(C) : Abstraction의 기능을 확장 (CountDisplay)
- Implementor(I/F) : 구현 클래스 계층의 최상위 클래스 (DisplayImpl)
- ConcreteImplementor(C) : Implementor 클래스 구체적 구현 (WinImpl, MacImpl)
Composite
▣ 정의
- 객체들의 관계를 트리구조로 구성하여 부분-집합 계층을 표현하는 패턴
▣ 활용
- 부분-집합 관계의 계층도를 표현해야 할 때
▣ 결과
- 하나의 일관된 계층도 정의
- 새로운 요소를 쉽게 추가
- 범용성 있게 설계
▣ 참여객체
- Component(I/F) : 집합 관계에 정의될 모든 객체에 대한 인터페이스 정의(공통의 행위 구현)
- Leaf(C) : 집합 관계에 포함되기만 하는 가장 기본이 되는 행위 정의
- Composite(C)(Children) : 복합 객체에 대한 행위를 정의
- Client : Component 인터페이스를 통해 집합 관계에 있는 객체들을 관리
Decorator
▣ 정의
- 객체에 추가 요소를 동적으로 장식 해가는 패턴
▣ 활용
- 동적으로 객체에 새로운 서비스를 추가할 때
▣ 결과
- 클라이언트에게 일관된 인터페이스를 제공하는 껍데기
▣ 참여객체 (Composite 에서 Decorator Class 추가)
- Component(I/F) : 동적으로 추가할 서비스를 가질 가능성이 있는 객체들에 대한 인터페이스
- ConcreteComponent(C) : 추가적인 서비스가 실제로 정의되어야 할 필요가 있는 객체
- Decorator(C)(Composite) : Component 객체에 대한 참조자를 관리하면서 Component에 정의된 인터페이스를 만족하도록 인터페이스를 정의
- ConcreteDecorator(C) : Component에 새롭게 추가할 서비스를 실제로 구현하는 클래스
Facade
▣ 정의 - 서브시스템의 복잡한 인터페이스를 단순화된 하나의 인터페이스로 제공 ▣ 활용 - 복잡한 서브시스템에 대한 단순한 인터페이스 제공이 필요할 때 ▣ 결과 - 서브시스템의 구성 요소 보호 - 서브시스템과 클라이언트 코드 간의 결합도를 낮춤 - 서브시스템 클래스를 사용하는 것을 완전히 막지는 않음. Facade 또는 서브시스템 클래스를 직접 사용할지 결정 ▣ 참여객체 - Facade : 서브시스템의 응용 프로그램 코드와 상호 동작 - Client : 패키지 내의 리소스들을 접근하기 위해 퍼사드 클래스를 사용하는 객체 - Package : 소프트웨어 라이브러리 / API 집합
Flyweight
▣ 정의
- 인스턴스를 가능한 한 공유시켜 쓸데없이 new를 하지 않도록 하는 패턴
▣ 활용
- 애플리케이션이 대량의 객체를 사용해야 할 때
- 객체 수가 너무 많아져 저장 비용이 너무 높아질 때
- 대부분의 객체 상태를 부가적인 것으로 만들 수 있을 때
- 애플리케이션이 객체 식별자에 비중을 두지 않는 경우 (식별자를 둔다는 것은 서로 다른 객체로 구별해야 한다는 것이고 이때는 flyweight 객체를 사용할 수 없음)
▣ 결과
- 공유해야 하는 인스턴스의 전체 수를 줄일 수 있다
- 객체별 본질적 상태와 양을 줄일 수 있다
- 부가적인 상태는 연산되거나 저장될 수 있다
▣ 참여객체
- Flyweight(A) : Flyweight 가 받아들일 수 있고, 부가적 상태에서 동작해야 하는 인터페이스를 선언
- ConcreteFlyweight(C) : Flyweight 인터페이스를 구현하고 내부적으로 갖고 있어야 하는 본질적 상태에 대한 저장소를 정의하고 있다. ConcreteFlyweight 객체는 공유할 수 있는 것이어야 한다. 그러므로 관리하는 어떤 상태라도 본질적인 것이어야 한다.
- UnsharedConcreteFlyweight(C) : 모든 Flyweight 서브클래스들이 공유될 필요는 없다. Flyweight 인터페이스는 공유를 가능하게 하지만 그것을 강요해서는 안 된다.
- FlyweightFactory(A)(Aggregation Flyweight) : Flyweight 객체를 생성하고 관리한다. Flyweight가 적절히 공유되도록 보장해야 한다. 클라이언트가 Flyweight를 요청하면 FlyweightFactory 객체는 이미 존재하는 인스턴스를 제공하거나, 만약 존재하지 않는다면 생성해야 한다.
Client : Flyweight에 대한 참조자를 관리하고 Flyweight의 부가적 상태를 저장한다.
Proxy
▣ 정의
- 바빠서 그 일을 할 수 없는 본 객체 대신, 대리인 객체가 어느 정도 일을 처리해 주는 패턴
- 객체를 감싸서 그 객체에 대한 접근을 제어
▣ 활용
- 다른 객체에 접근하기 위해 본인 객체는 은닉하고 대리인 객체를 둠 (객체에 대한 참조자 관리가 필요할때)
▣ 결과 (원가보스)
- 원격 프락시 : 원격에 있음에도 불구하고 바로 옆에 있는 것처럼 호출
- 가상 프락시 : 인스턴스가 필요한 시점에만 생성
- 보호용 프락시 : RealSubject 기능에 대해 엑세스 제한을 설정
스마트 프락시 : 객체에 대한 단순한 접근 외에 부가적인 작업 수행
▣ 참여객체
- Proxy : 실제로 참조할 대상에 대한 참조자를 관리한다. Subject 와 동일한 인터페이스를 제공하여 실제 대상을 대체할 수 있어야 한다. 실제 대상에 대한 접근을 제어하고 실제 대상의 생성과 삭제를 책임진다.
- Subject : RealSubject와 Proxy에 공통적인 인터페이스를 정의하고 있어, RealSubject가 요청되는 곳에 Proxy를 사용할 수 있게 한다.
- RealSubject : 프록시가 대표하는 실제 객체
Interpreter
▣ 정의
- 간단한 언어의 문법을 정의하는 방법과 그 언어로 문장을 구성하는 방법, 문장을 해석하는 방법을 제시
▣ 활용
- 해석이 필요한 언어가 존재하거나 추상구문트리로 언어에 정의된 문장을 표현하고자 할 때
- 정의할 언어 문법이 간단하고, 효율성은 큰 고려 사항이 아닐 때
▣ 결과
- 문법의 변경과 확장 및 구현 용이
- 표현식을 해석하는 새로운 방법 추가 가능
▣ 참여객체
- AbstractExpression(I/F) : 추상 구문 트리에 속한 모든 노드에 해당하는 클래스들이 공통으로 가져야 할 Interpret() 오퍼레이션을 추상 오퍼레이션으로 정의한다.
- TerminalExpression(C) : 문법에 정의한 터미널 기호와 관련된 해석 방법을 구현한다. 문장을 구성하는 모든 터미널 기호에 대해서 해당 클래스를 만들어야 한다.
- NonTerminalExpression(C) : 문법의 오른편에 나타나는 모든 기호에 대해서 클래스를 정의해야 한다.
- Context : 번역기에 대한 포괄적인 정보를 포함한다.
- Client : 언어로 정의한 특정 문장을 나타내는 추상 구문 트리이다. 이 추상 구문 트리는 NonterminalExpression 과 TerminalExpression 클래스의 인스턴스로 구성된다.
Template Method
▣ 정의
- 상위 클래스에서 처리의 흐름을 정하고 하위 클래스에서 구체적인 내용을 재정의하는 디자인 패턴
- 알고리즘의 개별 단계를 구현하는 방법을 서브클래스에서 결정한다.
▣ 활용
- 알고리즘의 변하지 않는 부분을 한 번 정의하고 다양해질 수 있는 부분을 서브플래스에서 정의할 수 있도록 구현하고자 할 때
- 서브클래스 사이의 공통적인 행위를 추출해 하나의 공통클래스로 정의할 때, 이는 일반화를 위한 refactoring의 예라 볼 수 있다. 차이를 보이는 부분을 템플릿 메소드로 정의하고, 나중에 상속받은 서브클래스가 정의하는 오퍼레이션을 호출하게 한다.
- 서브클래스의 확장을 제어할 수 있다. 이는 템플릿 메소드가 어떤 특정한 시점에 hook 오퍼레이션을 호출하도록 정의하면, 실제로 이 hook 오퍼레이션이 호출되는 순간 새로운 확장이 이루어진다.
▣ 결과
- 코드 재사용을 위한 기본 기술이다.
- “할리우드 제어 구조”를 만들어 내기도 하는데, 이는 “전화하지 마세요. 제가 전화할게요” 이다. 이를 클래스에 적용하면, 부모 클래스는 서브클래스에 정의된 오퍼레이션을 호출할 수 있지만 반대로는 되지 않는다.
▣ 참여객체
- AbstractClass(A) : 서브클래스들이 반드시 구현해야 하는 알고리즘 처리 단계 내의 기본 오퍼레이션이 무엇인지를 정의한다.
- ConcreteClass(C) : 서브클래스 마다 기본 오퍼레이션을 다르게 구현한다.