본문 바로가기

CS/디자인패턴

(12)
[디자인패턴] 메멘토 패턴 설명 캡슐화를 위배하지 않으면서 특정 객체의 상태를 따로 실체화해 둠으로써 나중에 객체의 상태를 복원할 수 있게 한다. 보통 다음과 같은 동작이 요구된다. 상태를 이전으로 되돌릴 수 있음 상태 객체에 대한 접근은 데이터에 대한 원 객체만 가능해야 함 어떤 프로그램은 undo(되감기) 기능을 요구하며, 이를 위해서는 현재 객체의 상태를 따로 분리하여 저장해둬야 한다. 이때 분리된 객체 메멘토가 가지고 있는 상태는 원 객체의 이전 정보를 담고 있으므로 (1) 원 객체만 상태 정보에 접근할 수 있어야 하며, (2) 중간에 악의적인 사용자가 마음대로 이전 상태 정보를 수정하여 반영할 수 있어서는 안 된다. 이를 위해서는 원 객체에서만 메멘토에 접근할 수 있게 하는 구현이 요구된다. 전체적인 메멘토 패턴의 동작 ..
[디자인패턴] 팩토리 패턴들 팩토리 관련 패턴은 대략 3개로 나눌 수 있다. 단순 팩토리 패턴: 객체 생성 로직을 캡슐화하여 클라이언트와의 결합도를 낮춘다. 팩토리 메서드 패턴: 객체 생성에 대한 인터페이스만 정의하고, 구체적인 생성은 서브 클래스에게 위임한다. 추상 팩토리 패턴: 함께 사용되거나 연관된 패밀리 객체 군을 생성하는 인터페이스를 정의한다. 각 객체를 생성하기 위한 인터페이스(메서드 각각)들을 정의할 때 팩토리 메서드나 프로토타입 패턴이 사용될 수 있다. 팩토리 메서드 패턴과 추상 팩토리 패턴의 경우 DIP를 중점적으로 생각하자... 단순 팩토리 패턴 객체를 생성하는 로직을 클라이언트로부터 숨겨 클라이언트와 객체 생성 책임 사이의 결합도를 낮추기 위한 패턴이다. 버튼 클래스의 서브 클래스들 중 하나를 선택하는 상황을 생..
[디자인패턴] Observer 패턴 설명 객체 사이에 1 대 N 의존 관계를 정의하여, 대상(subject) 객체의 상태 변화가 의존 객체(observers)에게 통지되고, 상태를 자동으로 업데이트한다. 객체 사이의 데이터 일관성을 유지하고 싶지만 결합도를 높이고 싶지는 않다. 예를 들어 데이터를 관리하는 클래스와 표를 보여주는 클래스(바, 파 차트, 표 등)들이 있을 때, 데이터가 변동될 때마다 표의 모습을 바꾸고 싶다고 생각해보자. 일단 데이터와 표를 담당하는 클래스가 분리되어 있으므로, 데이터를 시각화하기 위해서는 데이터 클래스가 표 클래스에게 자신의 데이터를 지속적으로 제공할 필요가 있다. 이때 각 표를 위한 클래스들의 인터페이스가 동일하다는 보장은 없으므로 단순히 구현한다면 데이터 클래스 내부에 업데이트를 요구하는 클래스들의 레퍼..
[디자인패턴] Chain Of Responsibility 패턴 설명 메시지를 보내는 객체와 해당 요청을 처리하는 객체 사이의 결합도를 낮춘다. 하나의 요청이 들어올 때 연결된 객체 리스트 사이를 이동하면서 해당 요청을 처리할 수 있는 객체까지 전달되어 처리한다. 요청을 처리하는 객체는 전달된 요청을 자신이 처리할 수 있다면 처리하고 아니면 자신이 알고 있는 다음 객체에게 넘긴다. 이처럼 책임 객체의 동작 방식이 체인처럼 연결되어 있어 책임 체인 패턴이라는 이름이 붙어 있다. 웹 애플리케이션 서버를 만들고 있는 상황을 생각해 보자. 외부에서 들어온 요청은 handleRequest(request, response)라는 단일 함수 내에서 분류되어 처리된다. 이때 HTTP 헤더는 현재 사용되고 있는 메서드는 무엇인지, 원하는 데이터 타입은 무엇인지 뿐만 아니라 수많은 정보..
[디자인패턴] Proxy 패턴 설명 proxy라는 단어는 "대리" 라는 의미를 가지고 있다. 이름에서 알 수 있듯이 proxy 패턴은 원 객체에 대한 접근을 제어하기 위해 대리자 역할을 수행한다. 프록시 객체는 원 객체에 대한 접근을 조절하거나 생성 및 소멸을 책임질 수 있으며, 원 객체에게 전달될 요청을 받아 넘기기 전에 해당 데이터를 이용하여 여러가지 동작을 추가적으로 취할 수 있으므로 간단한 로깅부터 시작하여 접근 제어, 캐싱 등 사용 방법이 매우 다양할 수 있는 것이 특징이다. gof 책에서는 다음과 같은 활용 예시를 제시하고 있다. 원격지 프록시(remote proxy): 서로 다른 주소 공간에 존재하는 객체를 가리키는 객체로, 프록시 객체 자체는 로컬에 존재한다. 로컬의 프록시 객체는 네트워크 통신을 통해 원격의 실제 객체..
[디자인패턴] Mediator 패턴 설명 다양한 기능을 객체 단위로 분산하면 해당 객체들 사이에 다양한 연관 관계가 발생한다. 시스템을 객체 단위로 분할하면 재사용성이 높아질 수 있지만, 분할 수준이 높아지다보면 객체들이 상호작용에 따른 연관관계가 많아지고, 서로에 의존하게 되는 문제가 발생한다. 이 경우 객체를 분할했음에도 객체들 사이의 결합도가 높아 크게 보면 사실상 하나의 큰 덩어리로 구현하는 것과 유사한 상황이 나타난다. 아래 가상의 기기를 보면서 구체적으로 생각해보자. 위 기기는 다음과 같이 동작한다. A ~ F 버튼을 누르면 클릭한 버튼의 문자가 디스플레이에 추가된다. SAVE 버튼을 누르면 현재까지 누른 버튼 리스트를 외부로 전달한다. RESET 버튼을 누르면 누른 버튼 리스트를 초기화한다. 디스플레이도 초기화된다. LED는 ..
[디자인패턴] Facade 패턴 설명 복잡한 시스템 구성을 쉽게 사용할 수 있도록 획일화 된 하나의 상위 레벨의 인터페이스를 제공한다. 하나의 시스템에는 다양한 구성요소가 존재한다. 이때 시스템이 확장되고 보다 구체적으로 설계됨에 따라 이를 구성하는 각 요소들의 복잡도가 높아진다. 현재 시스템을 잘 알고 있다면 이러한 복잡한 아키텍처를 이해하면서 구성요소를 조합하여 새로운 프로그램을 만들 수 있겠지만, 단순히 현재 라이브러리를 사용하고 싶은 개발자 입장에서는 점점 복잡해지는 아키텍처를 전부 이해하며 개발하기가 어렵다. 또한 각 모듈이 제공하는 기능 전부를 사용하는 경우도 드물다. 따라서 사용자가 시스템의 구성요소 각각을 직접 접근하는 대신, 구성요소를 이용하여 사용자가 원하는 기능을 수행하는 Facade 클래스를 두고, 해당 클래스가 ..
[디자인패턴] SOLID 원칙 SOLID 객체 지향 디자인에 대하여 이해, 변경, 확장 및 유지관리하기 쉽도록 하는 설계 원칙으로, 설계 평가에 사용될 수 있다. SOLID를 구성하는 원칙은 다음과 같다. Single Responsibility Principle: 클래스의 책임을 하나만 둬서 변경해야 할 이유를 제한하자. Open Close Principle: 확장에는 열린 상태로, 변경에는 닫힌 상태로 두자. Liskov Substitution Principle: 서브 타입은 베이스 타입으로 손실 없이 바뀔 수 있어야 한다. Interface Segregation Principle: 하나의 범용 인터페이스보다는 여러 개의 개별 인터페이스를 만들자. Dependency Inversion Principle: 추상적인 것이 구체적인 것에..