디자인 패턴 세미나를 통해 공부한 내용을 업로드합니다. 각 챕터의 코드는 Github에 업로드하고, 내용은 노션에 기록해 두었습니다.
Chapter1 : 디자인 패턴의 소개와 전략 패턴
- 필요한 기초 지식
추상화
,캡슐화
,다형성
,상속
- 객체지향 원칙
- 바뀌는 부분은
캡슐화
- 상속보다는
구성
을 활용 - 구현보다는
인터페이스에 맞춰 프로그래밍
- 바뀌는 부분은
- 객체지향 패턴
- 전략 패턴
- 전략 패턴은 알고리즘군을 정의하고 캡슐화해서 각각 의 알고리즘군을 수정해서 쓸 수 있게 해 줍니다. 전략 패턴을 사용하면 클라이언트로부터 알고리즘을 분리해서 독립적으로 변경할 수 있습니다.
- 전략 패턴
- 핵심 정리
- 훌륭한 객체지향 디자인을 위해서는 재사용성, 확장성, 관리의 용이성을 가져야함.
- 패턴이 코드를 바로 제공하는 것은 아니고, 디자인 문제의 보편적인 해법을 제공합니다.
- 대부분의 패턴은 시스템의 일부분을 독립적으로 변경하는 방법을 제공합니다.
- 패턴은 다른 개발자와의 의사소통을 극대화하는 역할을 합니다.
Chapter2 : 옵저버 패턴
- 객체지향 원칙
- 상호 작용하는 객체 사이에서는 가능하면 느슨한 결합을 사용해야한다.
훨씬 더 유연하고 변화에 강한 디자인
- 상호 작용하는 객체 사이에서는 가능하면 느슨한 결합을 사용해야한다.
- 객체지향 패턴
- 옵저버 패턴
- 일련의 객체 사이에서 일대다 의존성을 정의하며 한 객체의 상태가 바뀌면 그 객체에 의존 하는 모든 객체들에게 연락이 갑니다.
- 옵저버 패턴
- 핵심정리
- 옵저버 패턴은 객체들 사이에 일대다 관계를 정의합니다.
- 주제는 옵저버들이
Observer
인터페이스를 구현한다는 것을 제외하면 옵저버에 관해 전혀 모르기 때문에 이들은느슨한 결합
입니다. - 옵저버 패턴을 사용하면
주제 → 옵저버(푸시 방식),주제←옵저버(풀 방식)
이 있습니다.- 일반적으로 풀 방식이 맞는 방식입니다.
Chapter3 : 데코레이터 패턴
- 객체지향 원칙
클래스는 확장에는 열려 있고, 변경에는 닫혀 있어야 한다.(OCP)
- 객체지향 패턴
- 데코레이터 패턴
- 객체에 추가 요소를 동적으로 더할 수 있으며, 서브클래스르 만들 때보다 훨씬 유연하게 기능을 확장할 수 있습니다.
- 데코레이터 패턴
- 핵심정리
- 디자인의 유연성 면에서 보면 상속을 확장하는 일은 좋지 않습니다.
- 데코레이터 클래스의 형식은 그 클래스가 감싸는 클래스 형식을 반영합니다.
- 데코레이터는 자기가 감싸고 있는 구성 요소의 메소드를 호출한 결과에 새로운 기능을 더함으로써 행동을 확장합니다.
- 데코레이터 패턴을 사용하면 자잘한 객체가 많이 추가될 수 있고, 너무 많이 사용하면 코드가 필요 이상으로 복잡해집니다.
Chapter4 : 팩토리 패턴
- 객체지향 원칙
- 추상화된 것에 의존하게 만들고 구상 클래스에 의존하지 않게 만듭니다.
- 객체지향 패턴
- 추상 팩토리 패턴
- 구상 클래스에 의존하지 않고도 서로 연관되거나 의존적인 객체로 이루어진 제품군을 생성하는 인터페이스를 제공합니다.
- 구상 클래스는 서브클래스에서 만듭니다.
- 팩토리 메소드 패턴
- 객체를 생성할 때 필요한 인터페이스를 만듭니다.
- 어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정합니다.
- 팩토리 메소드를 사용하면 인스턴스 만드는 일을 서브클래스에 맡길 수 있습니다.
- 추상 팩토리 패턴
- 핵심 정리
- 팩토리를 쓰면 객체 생성을 캡슐화할 수 있습니다.
팩토리 메소드 패턴은 상속
을 활용합니다.- 객체 생성은 서브클래스에 맡깁니다.
- 서브 클래스는 팩토리 메소드를 구현해서 객체를 생성합니다.
추상 팩토리 패턴은 객체 구성
을 활용합니다.- 팩토리 인터페이스에서 선언한 메소드에서 객체 생성이 구현됩니다.
- 모든 팩토리 패턴은 애플리케이션의 구상 클래스 의존성을 줄여줌으로써 느슨한 결합을 도와줍니다.
- 의존성 뒤집기 원칙에 따르면 구상 형식 의존을 피하고 추상화를 지향할 수 있습니다.
Chapter5 : 싱글턴 패턴
- 객체지향 패턴
- 싱글턴 패턴
- 클래스 인스턴스를 하나만 만들고, 그 인스턴스로의 전역 접근을 제공합니다.
- 싱글턴 패턴
- 핵심정리
- 어떤 클래스에 싱글턴 패턴을 적용하면 그 클래스의 인스턴스가 1개만 있도록 할 수 있습니다.
- 싱글턴 패턴을 사용하면 하나뿐인 인스턴스를 어디서든지 접근할 수 있습니다.
- 자바에서 싱글턴 패턴을 구현할때는
private
생성자와 정적 메소드, 정적 변수를 사용합니다. - 자바의
enum
을 쓰면 간단하게 싱글턴을 구현할 수 있습니다.
Chapter6 : 커맨드 패턴
- 객체지향 패턴
- 커맨드 패턴
- 요청 내역을
객체로 캡슐화
해서 객체를 서로 다른 요청 내역에 따라매개변수화
하여 요청을 큐에 저장하거나 로그로 기록하거나 작업 취소 기능을 사용할 수 있습니다.
- 요청 내역을
- 커맨드 패턴
- 핵심 정리
- 커맨드 패턴을 사용하면 요청하는 객체와 요청을 수행하는 객체를 분리할 수 있습니다.
- 인보커는 무언가 요청할 때 커맨드 객체의
execute()
메소드를 호출하면 됩니다. - 커맨드는 인보커를 매개변수화하며 실행 중에 동적으로 매개변수화를 설정할 수도 있습니다.
execute()
메소드가 마지막으로 호출되기 전의 상태로 되돌리는 작업 취소 메소드를 구현하면 커맨드 패턴으로 작업 취소 기능을 구현할 수도 있습니다.- 매크로 커맨드는 커맨드를 확장해서 여러 개의 커맨드를 한 번에 호출할 수 있게 해 주는 가장 간편한 방법이고 작업 취소 기능을 어렵지 않게 구현할 수 있습니다.
Chapter7 : 어댑터 패턴과 퍼사드 패턴
- 객체지향 원칙
- 진짜 절친에게만 이야기해야 한다.
- 최소 결합을 해야 한다는 사실을 알려주는 새로운 원칙의 추가
- 진짜 절친에게만 이야기해야 한다.
- 객체지향 패턴
- 어댑터 패턴
- 특정 클래스
인터페이스를 클라이언트에서 요구하는 다른 인터페이스로 변환
합니다. 인터페이스가 호환되지 않아 같이 쓸 수 없었던 클래스를 사용할 수 있게 도와줍니다.
- 특정 클래스
- 퍼사드 패턴
서브시스템에 있는 일련의 인터페이스를 통합 인터페이스로 묶어 줍니다.
또한 고수준의 인터페이스도 정의하므로 서브시스템을 더 편리하게 사용할 수 있습니다.
- 어댑터 패턴
- 핵심 정리
- 어댑터는 인터페이스를 클라이언트에서 원하는 인터페이스로 바꾸는 역할을 합니다.
- 퍼사드는 클라이언트를 복잡한 서브시스템과 분리하는 역할을 합니다.
- 어댑터 패턴에는 객체 어댑터 패턴과 클래스 어댑터 패턴이 있습니다. 클래스 어댑터를 쓰려면 다중 상속이 가능해야 합니다.
- 퍼사드 패턴에서는 서브시스템으로 퍼사드를 만들고 진짜 작업은 서브클래스에 맡깁니다.
Chapter10 : 스테이트 패턴
- 객체지향 패턴
- 상태 패턴
- 내부 상태가 바뀜에 따라 객체의 행동이 바뀔 수 있도록 해줍니다. 마치 객체의 클래스가 바뀌는 것 같은 결과를 얻을 수 있습니다.
- 상태 패턴
- 핵심 정리
- 상태 패턴을 사용하면 내부 상태를 바탕으로 여러 가지 서로 다른 행동을 사용할 수 있습니다.
Context
객체는 현재 상테에게 행동을 위임합니다.- 각 상태를 클래스로 캡슐화해서 나중에 변경해야 하는 내용을 국지화할 수 있습니다.
- 상태 패턴과 전략패턴의 클래스 다이어그램은 똑같지만 용도는 다릅니다.
- 상태 패턴을 쓰면 디자인에 필요한 클래스의 개수가 늘어납니다.
State
클래스를 여러Context
객체의 인스턴에게 공유하도록 디자인할 수도 있습니다.
Chapter8 : 템플릿 메소드 패턴
- 객체지향 원칙
- 먼저 연락하지 마세요. 저희가 연락 드리겠습니다.
- 객체지향 패턴
- 템플릿 메소드 패턴
- 알고리즘의 골격을 정의합니다. 템플릿 메소드를 사용하면 알고리즘의 일부 단계를 서브클래스 에서 구현할 수 있으며, 알고리즘의 구조는 그대로 유지하면서 알고리즘의 특정 단계를 서브클래스에서 재정의할 수도 있습니다.
- 템플릿 메소드 패턴
- 핵심 정리
- 템플릿 메소드는 알고리즘의 단계를 정의하며 일부 단계를 서브클래스에서 구현하도록 할 수 있습니다.
- 템플릿 메소드는 코드 재사용에 큰 도움이 됩니다.
- 후크는 추상 클래스에 들어있는 메소드로 아무 일도 하지 않거나 기본 행동만을 정의합니다. 서브 클래스에서 후크를 오버라이드 할 수 있습니다.
- 할리우드 원칙에 의하면, 저수준 모듈을 얼제 어떻게 호출할지는 고수준 모듈에서 결정하는 것이 좋습니다.
- 템플릿 메소드 패턴은 실전에서도 꽤 자주 쓰이지만 반드시 '교과서적인' 방식으로 적용되진 않습니다.
- 전략 패턴과 템플릿 메소드 패턴 모두 알고리즘을
캡슐화
하는 패턴이지만 전략 패턴은상속
을, 템플릿 메소드 패턴은구성
을 사용합니다. - 팩토리 메소드 패턴은
특화된 템플릿 메소드 패턴
입니다.
Chapter9 : 이터레이터와 컴포지트 패턴
- 객체지향 원칙
- 어떤 클래스가 바뀌는 이유는 하나뿐이어야만 한다.
- 객체지향 패턴
- 반복자 패턴
- 컬렉션의 구현 방법을 노출하지 않으면서 집합체 내의 모든 항목에 접근하는 방법을 제공합니다.
- 컴포지트 패턴
- 객체를 트리구조로 구성해서 부분- 전체 계층 구조를 구현합니다. 컴포지트 패턴을 사용하면 클라이언트에서 개별 객체와 복합 객체를 똑같은 방법으로 다룰 수 있습니다.
- 반복자 패턴
- 핵심 정리
- 반복자 패턴
- 반복자를 사용하면 내부 구조를 드러내지 않으면서도 클라이언트가 컬렉션 안에 들어있는 모든 원소에 접근하도록 할 수 있습니다.
- 반복자 패턴을 사용하면 반복 작업을 별도의 객체로 캡슐화하고, 똑같은 인터페이스를 적용할 수 있으므로 집합체의 객체를 활용하는 코드를 만들 때 다형성을 활용할 수 있습니다.
- 한 클래스에는 될 수 있으면 한가지 역할만 부여하는 것이 좋습니다.
- 컴포지트 패턴
- 컴포지트 패턴을 사용하면 클라이언트가 개별 객체와 복합 객체를 똑같은 방법으로 다룰 수 있습니다.
- 반복자 패턴
Chapter11 : 프록시 패턴
- 객체지향 패턴
- 프록시 패턴
- 특정 객체로의 접근을 제어하는 대리인(특정 객체를 대변하는 객체)을 제공합니다.
- 프록시 패턴
- 핵심 정리
- 프록시 패턴을 사용하면 어떤 객체의 대리인을 내세워서 클라이언트의 접근을 제어할 수 있다.
- 원격 프록시는 클라이언트와 원격 객체 사이의 데이터 전달을 관리한다.
- 가상 프록시는 인스턴스를 만드는 데 많은 비용이 드는 객체로의 접근을 제어한다.
- 보호 프록시는 호출하는 쪽의 권한에 따라서 객체에 있는 메소드로의 접근을 제어한다.
- 그 외에도 캐싱 프록시, 동기화 프록시, 방화벽 프록시, 지연 복사 프록시와 같은 다양한 변형된 프록시 패턴이 있다.
Chapter12 : 컴파운드 패턴
- 객체지향 패턴
- 복합 패턴
- 2개 이상의 패턴을 결합해서 일반적으로 자주 등장하는 문제들의 해법을 제공한다.
- 복합 패턴
- 핵심 정리
모델-뷰-컨트롤러(MVC)
는 옵저버, 전략, 컴포지트 패턴으로 이루어진 복합 패턴이다.- 모델은 옵저버 패턴을 사용해 의존성을 없애고, 상태 변경을 알린다.
- 컨트롤러는 뷰의 전략 객체로, 뷰는 컨트롤러를 바꿔 다른 행동을 할 수 있다.
- 뷰는 컴포지트 패턴을 사용해 사용자 인터페이스를 구현한다.