소프트웨어 설계에서 반복적으로 발생하는 문제에 대해 반복적으로 적용할 수 있는 해결 방법을 디자인 패턴이라고 부른다. 디자인 패턴의 목적은 설계를 재사용하는 것이다.
디자인 패턴은 다양한 변경을 다루기 위해 반복적으로 재사용할 수 있는 설계의 묶음이다.
디자인 패턴이 설계를 재사용하기 위한 것이라면 프레임워크는 설계와 코드를 함께 재사용하기 위한 것이다. 프레임워크는 애플리케이션의 아키텍처 구현 코드의 형태로 제공한다.
패턴의 잘 알려진 이름을 사용함으로써 "인터페이스 하나 추가하고, 이 인터페이스를 구체화하는 클래스를 만든 후 객체의 생성자나 setter 메서드를 할당해서 런타임 시에 알고리즘을 바꿀 수 있게 하자"는 장황한 대화가 STRATEGY 패턴을 적용하자는 단순한 대화로 바뀐다. 패턴의 이름은 높은 수준의 대화를 가능하게 하는 원천이다.
패턴을 분류하는 가장 일반적인 방법은 패턴의 범위나 적용 단계에 따라 아키텍처 패턴, 분석 패턴, 디자인 패턴, 이디엄의 4가지로 분류하는 것이다.
아키텍처, 디자인 패턴, 이디엄이 주로 기술적인 문제를 해결하는 데 초점을 맞추고 있다면 분석 패턴은 도메인 내의 개념적인 문제를 해결하는 데 초점을 맞춘다. 분석 패턴은 업무 모델링 시에 발견되는 공통적인 구조를 표현하는 개념들의 집합이다.
패턴의 구성 요소는 클래스가 아니라 '역할'이다. 클라이언트가 개별 객체와 복합 객체를 동일하게 취급할 수 있는 COMPOSITE 패턴을 살펴보자. 패턴의 구성 요소인 Component, Composite, Leaf는 클래스가 아니라 협력에 참여하는 객체들의 역할이다. Component는 역할이기 때문에 Component가 제공하는 오퍼레이션을 구현하는 어떤 객체라도 Component의 역할을 수행할 수 있다.

역할은 동일한 오퍼레이션에 대해 응답할 수 있는 책임의 집합을 암시하기 때문에 그림 15.2와 같이 하나의 객체가 세 가지 역할 모두를 수행하더라도 문제가 없다.

반대로 다수의 클래스가 동일한 역할을 구현할 수도 있다. 15.3은 8장에서 살펴본 중복 할인 정책의 구조를 다이어그램으로 표현한 것이다. 중복 할인 설계의 기본 구조는 COMPOSITE 패턴을 따른다.

영화 예매 시스템에서 Movie가 DiscountPolicy 상속 계층을 합성 관계로 유지해야 하는 다양한 설계 원칙과 이유에 대해 장황하게 설명했지만 사실 이 설계는 STRATEGY 패턴을 적용한 예다. STRATEGY 패턴의 목적은 알고리즘의 변경을 캡슐화하는 것이고 이를 구현하기 위해 객체 합성을 이용한다.

STRATEGY 패턴을 이용하면 Movie와 DiscountPolicy 사이의 결합도를 낮게 유지할 수 있기 때문에 런타임에 알고리즘을 변경할 수 있다.
물론 변경을 캡슐화하는 방법은 상속을 이용할 수도 있다. 그림 15.5는 Movie의 인터페이스 측면에서 그림 15.4와 동일하지만 변경을 캡슐화하기 위해 상속을 사용한 예다. 여기서 변하지 않는 부분은 Movie고 변하는 부분은 AmountDiscountMovie와 PercentDiscountMovie다. 그리고 변경하지 않는 부분은 부모 클래스로, 변하는 부분은 자식 클래스로 분리함으로써 변경을 캡슐화한다. 이처럼 알고리즘을 캡슐화하기 위해 합성 관계가 아닌 상속 관계를 사용하는 것을 TEMPLATE METHOD 패턴이라고 부른다.

상속을 사용할 경우에는 추상 메서드를 사용해 변경을 캡슐화해야 한다. 그림 15.5의calculateDiscountAmount 메서드가 바로 서브 클래스의 변경을 캡슐화하기 위해 사용되는 추상 메서드다. 부모 클래스의 calculateFee 메서드에서 calculateDiscountAmount 메서드를 호출하고 자식 클래스들이 이 메서드를 오버라이딩해서 변하는 부분을 구현한다는 것이 중요하다. 이것은 TEMPLATE METHOD 패턴의 전형적인 구현 방법이다.
그림 15.6의 핸드폰 과금 시스템 설계는 DECORATOR 패턴을 기반으로 한다. DECORATOR 패턴은 객체의 행동을 동적으로 추가할 수 있게 해주는 패턴으로서 기본적으로 객체의 행동을 결합하기 위해 객체 합성을 사용한다. DECORATOR 패턴은 선택적인 행동의 개수와 순서에 대해 변경을 캡슐화할 수 있다.

패턴은 공통적인 문제에 적절한 해법을 제공하지만 공통적인 해법이 우리가 직면한 문제에 적합하지 않을 수도 있다. 문제를 분석하고 창의력을 발휘함으로써 패턴을 현재의 문제에 적합하도록 적절하게 수정하라.
디자인 패턴은 프로그래밍 언어에 독립적으로 재사용 가능한 설계 아이디어를 제공하는 것을 목적으로 한다. 따라서 언어에 종속적인 구현 코드를 정의하지 않기 때문에 디자인 패턴을 적용하기 위해서는 설계 아이디어를 프로그래밍 언어의 특성에 맞춰 가공해야 하고 매번 구현 코드를 재작성해야 한다는 단점이 있다.
가장 이상적인 형태의 재사용 방법은 설계 재사용과 코드 재사용을 적절한 수준으로 조합하는 것이다. 설계를 재사용하면서도 유사한 코드를 반복적으로 구현하는 문제를 피할 수 있는 방법은 없을까? 이 질문에 대한 객체지향 커뮤니티의 대답이 바로 프레임워크다.
프레임워크란 '추상 클래스나 인터페이스를 정의하고 인스턴스 사이의 상호작용을 통해 시스템 전체 혹은 일부를 구현해 놓은 재사용 가능한 설계', 또는 '애플리케이션 개발자가 현재의 요구사항에 맞게 커스터마이징할 수 있는 애플리케이션의 골격'을 의미한다. 첫 번째 정의가 프레임워크의 구조적인 측면에 초점을 맞추고 있다면 두 번째 정의는 코드와 설계의 재사용이라는 프레임워크의 사용 목적에 초점을 맞춘다.
프레임워크의 핵심은 추상 클래스나 인터페이스와 같은 추상화라고 할 수 있다.
그림 15.7은 핸드폰 과금 시스템에서 추상화에 해당하는 부분을 짙은 색으로 표시한 것이다. 그림에서 알 수 있듯 구체적인 클래스는 RatePolicy, AddtionalRatePolicy, FeeCondition에 의존하지만 추상화들은 구체 클래스에 의존하지 않는다는 것을 알 수 있다. 이 설계는 9장에서 살펴본 의존성 역전 원칙에 기반하고 있는 것이다.

의존성 역전 원리는 프레임워크의 가장 기본적인 설계 메커니즘이다. 의존성 역전은 의존성의 방향뿐만 아니라 제어 흐름의 주체 역시 역전시킨다. 앞서 설명한 것처럼 상위 정책이 구체적인 세부사항에 의존하는 전통적인 구조에서는 상위 정책의 코드가 하부의 구체적인 코드를 호출한다.
그러나 의존성을 역전시킨 객체지향 구조에서는 반대로 프레임워크가 애플리케이션에 속하는 서브클래스의 메서드를 호출한다. 따라서 프레임워크를 사용할 경우 개별 애플리케이션에서 프레임워크로 제어 흐름의 주체가 이동한다. 즉, 의존성을 역전시키면 제어 흐름의 주체 역시 역전된다. 이를 제어 역전(Inversion Of Control) 원리 또는 할리우드 원리라고 한다.

특정한 기본 정책을 구현하는 개발자는 FeeCondition을 대체할 서브타입만 개발하면 프레임워크에 정의된 플로우에 따라 요금이 계산된다.