디자인 패턴 23

비지터 패턴 (Visitor Pattern)

비지터 패턴 기존 코드를 변경하지 않고 새로운 기능을 추가하는 방법 더블 디스패치 (Double Dispatch) 를 활용할 수 있다. 아래와 같은 경우 해당 패턴을 적용해 볼 수 있다. 특정 클래스에 SRP 를 지키고 싶어 더는 책임을 늘리고 싶지 않을 때 버그가 발생할 수 있으니 더 이상 코드를 작성하고 싶지 않을 때 해당 코드는 다른 곳에서도 사용될 수 있을거 같다 라는 생각이 들 때 비지터 패턴 적용 전 특정 디바이스에 도형을 그려야 한다. 디바이스 클래스를 각 구체적인 디바이스 (ex. phone, watch) 들이 상속하고 Shape 인터페이스를 도형들이 implements 한다. Device 클래스와 그것을 구현한 각 디바이스들은 모두 비어 있는 클래스이다. public class Devi..

디자인 패턴 2022.08.13

템플릿 메서드 패턴 (Template Method Pattern)

템플릿 메서드 패턴 알고리즘 구조를 서브 클래스가 확장할 수 있도록 템플릿으로 제공하는 방법 추상 클래스는 템플릿을 제공하고 하위 클래스는 구체적인 알고리즘을 사용한다. 예로, 아래와 같은 구조의 알고리즘이 있다 가정하자. 파일을 읽은 뒤 적절히 파싱한다. 그리고 출력한다. 위 알고리즘을 템플릿으로 제공하고 각각의 기능 (1, 2, 3) 들 중 달라질 수 있는 부분이 있다면 서브 클래스는 달라지는 부분만 직접 구현한다. AbstractClass 의 templateMethod 메소드는 알고리즘의 구조를 표현하는 메소드이다. 템플릿 메서드 패턴 적용 전 간단하게 숫자로만 이루어진 .txt 파일을 읽어서 해당 파일의 숫자들을 모두 덧셈한 결과를 알려주는 기능을 구현해보자. numbers.txt 파일은 아래와 ..

디자인 패턴 2022.08.13

전략 패턴 (Strategy Pattern)

전략 패턴 여러 알고리즘들을 캡슐화하고 상호 교환 가능하게 만드는 패턴 컨텍스트에서 사용할 알고리즘들을 클라이언트에서 선택한다. 즉, 특정 업무를 수행하는 방법이 여러가지 일 경우 여러가지 방법들을 각각의 클래스로 캡슐화하면 캡슐화된 것을 공통 인터페이스로 추상화하여 업무를 수행하는 Client 에서는 공통 인터페이스를 사용하게 하여 Client 코드는 변경되지 않고도 여러 방법들을 바꿔 낄 수 있다. Context : 원래 로직을 수행하던 클래스 ConcreteStrategy : 각각의 알고리즘들이 구현된 클래스 Strategy : 추상화된 알고리즘 수행 인터페이스 전략 패턴 적용 전 "무궁화 꽃이 피었습니다" 를 실행하는 프로그램이 있다. 이 게임은 "무궁화 꽃이" 까지는 파란불이며, "피었습니다."..

디자인 패턴 2022.08.13

상태 패턴 (State Pattern)

상태 패턴 객체 내부 상태 변경에 따라 객체의 행동이 달라지는 패턴 상태에 특화된 행동들을 분리해 낼 수 있으며, 새로운 행동을 추가하더라도 다른 행동에 영향을 주지 않는다. 예로 티비가 켜져있다면 음량버튼을 누르면 음량이 증가하거나 감소한다. 하지만 티비의 전원버튼을 끈다면 음량버튼을 아무리 눌러도 티비의 음량은 바뀌지 않는다. 즉, 티비 전원의 상태에 (리모컨의 상태) 따라 행동이 바뀌는 것이다. 상태 패턴 적용 전 온라인 강의가 있고 이것을 학생들이 수강할 수 있다고 하자. 온라인 강의에 학생을 추가하거나 리뷰를 달 수 있는데 이 때 온라인 강의 상태에 따라 학생 추가와 리뷰 등록이 다르게 작동한다. Client public class Client { public static void main(S..

디자인 패턴 2022.08.13

메멘토 패턴 (Memento Pattern)

메멘토 패턴 캡슐화를 유지하면서 객체 내부 상태를 외부에 저장하는 방법 객체 상태를 외부에 저장했다가 해당 상태로 다시 복귀할 수 있다. Originator - 우리가 저장할 객체이다. Originator 의 state 를 저장할 것이다. CareTaker - Originator 의 내부 정보를 CareTaker 가 가져와서 저장한다. Memento - 내부정보를 추상화한 클래스이다. CareTaker 는 Originator 의 디테일한 정보를 직접적으로 가지는 것이 아니라Memento 타입으로 가진다. Memento 는 Immutable 한 객체여야 한다. 메멘토 패턴 적용 전 게임 중에 게임을 중지시켰다가 다시 실행해도 중지 전까지 스코어는 유지되어야 한다. 간단하게 코드로 보면 아래와 같이 구현해 ..

디자인 패턴 2022.08.12

중재자 패턴 (Mediator pattern)

중재자 패턴 여러 객체들이 소통하는 방법을 캡슐화하는 패턴 여러 컴포넌트간의 결합도를 중재자를 통해 낮출 수 있다. 한 예로 비행기들은 관제탑이라는 Mediator 를 통해 서로 소통하는데, 이를 떠올리면서 학습하여 보자. 중재자 패턴 적용 전 호텔과 호텔의 여러 서비스들에 대한 코드이다. 먼저 호텔을 살펴보자. public class Hotel { public static void main(String[] args) { Guest guest = new Guest(); guest.getTowel(3); guest.dinner(); Restaurant restaurant = new Restaurant(); restaurant.clean(); } } main 에서 guest (손님) 가 타월을 달라고 요청..

디자인 패턴 2022.08.11

이터레이터 패턴 (Iterator Pattern)

이터레이터 패턴 집합 객체 내부 구조를 노출시키지 않고 순회하는 방법을 제공하는 패턴 집합 객체를 순회하는 클라이언트 코드를 변경하지 않고 다양한 순회 방법을 제공할 수 있다. 이터레이터 패턴 적용 전 Board 는 Post 들을 관리하는 객체이다. 먼저 Client 코드를 살펴보자. Client public class Client { public static void main(String[] args) { Board board = new Board(); board.addPost("디자인 패턴 게임"); board.addPost("디자인 패턴을 배워보아요"); board.addPost("모든 코더들은 디자인 패턴을 학습해야할까요?"); List posts = board.getPosts(); for (Po..

디자인 패턴 2022.08.04

인터프리터 패턴 (Interpreter Pattern)

인터프리터 패턴 자주 등장하는 문제를 간단한 언어로 정의하고 재사용하는 패턴 반복되는 문제 패턴을 언어 또는 문법으로 정의하고 확장할 수 있다. ex. 정규표현식 [참고] 인터프리터는 사람이 작성한 코드를 하드웨어가 이해할 수 있도록 변환해주는 장치이다. 다이어그램을 보면 컴포짓 패턴과 매우 유사하다. Context 는 모든 Expression 에서 사용하는 공통된 정보가 담겨있다. Expression 은 우리가 표현하는 문법을 나타내는데 Context 가 들어있는 것을 볼 수 있다. TerminalExpression 은 그 자체로 종료되는 Expression 이고, Non TerminalExpression 은 다른 Expression 들을 재귀적으로 참조하고 있는 Expression 이다. 인터프리터 ..

디자인 패턴 2022.08.03

커맨드 패턴 (Command Pattern)

커맨드 패턴 (Command Pattern) 요청을 캡슐화하여 호출자(invoker) 와 수신자 (receiver) 를 분리하는 패턴 요청을 하는 쪽과 요청을 처리하는 쪽을 디커플링 시킨다. 요청을 처리하는 방법이 바뀌더라도 호출자 코드는 변경되지 않는다. 커맨드 패턴 적용 전 불을 껏다 켰다 할 수 있는 Button 클래스가 있고 불에 해당하는 Light 클래스가 있다고 해보자. public class Light { private boolean isOn; public void on() { System.out.println("불을 켭니다."); this.isOn = true; } public void off() { System.out.println("불을 끕니다."); this.isOn = false; ..

디자인 패턴 2022.08.02

책임 연쇄 패턴 (Chain of Responsibility Pattern)

책임 연쇄 패턴 (Chain of Responsibility Pattern) 요청을 보내는 쪽(sender)과 요청을 처리하는(receiver) 쪽을 분리하는 패턴 핸들러 체인을 사용해서 요청을 처리한다. 클라이언트로부터의 요청을 처리할 수 있는 처리 객체를 Chain 으로 만들어 결합을 느슨하게 하기 위해 만들어진 패턴. 일반적으로 요청을 처리할 수 있는 객체를 찾을때 까지 집한 안에서 요청을 전달한다. 책임 연쇄 패턴 적용 전 클라이언트가 특정 핸들러를 사용할 때, 이 클라이언트가 해당 핸들러를 사용할 수 있는 사용자 인지 인증해야 하는 로직이 있다고 가정해보자. 클라이언트 코드는 아래와 같다. public class Client { public static void main(String[] args..

디자인 패턴 2022.08.02