Preface
이번 장에선 디자인 패턴의 8가지 종류를 공부했다.
개념 자체는 어렵지 않지만, 다양한 패턴을 실제 코드에 자연스럽게 녹아들게 하기까진 많은 시간과 노력이 필요할 것 같다.
추후 시간이 될 때 디자인 패턴 전문 서적을 구입해 읽어볼 생각이다.
자바 카테고리에 있는 책과 동일한 책이지만, 후반부에선 스프링에 대해 다뤄서 스프링 카테고리에 글을 업로드한다.
- 디자인 패턴: 표준 설계 패턴
→ OOP의 특성 중 상속(extends), 인터페이스(interface), 합성(객체를 속성으로 사용: 객체 참조 변수를 가짐)을 이용한다.
- 디자인 패턴의 종류
1. 생성 패턴
1) 싱글톤(Singleton)
2) 팩토리 메서드(Factory Method)
3) 추상 팩토리(Abstract Factory)
4) 빌더(Builder)
5) 프로토타입(Prototype)
2. 구조 패턴
1) 어댑터(Adapter)
2) 브릿지(Bridge)
3) 컴포짓(Composite)
4) 데코레이터(Decorator)
5) 퍼사드(Facade)
6) 플라이웨이트(Flyweight)
7) 프록시(Proxy)
3. 행동 패턴
1) 책임 연쇄(Chain-of-Responsibility)
2) 커맨드(Command)
3) 인터프리터(Interpreter)
4) 이터레이터(Iterator)
5) 중재자(Mediator)
6) 메멘토(Memento)
7) 옵저버(Observer)
8) 상태(State)
9) 전략(Strategy)
10) 템플릿 메소드(Template Method)
11) 비지터(Visitor)
→ 패턴 요약: https://m.hanbit.co.kr/channel/category/category_view.html?cms_code=CMS8616098823
[Design pattern] 많이 쓰는 14가지 핵심 GoF 디자인 패턴의 종류
디자인 패턴을 활용하면 단지 코드만 ‘재사용’하는 것이 아니라, 더 큰 그림을 그리기 위한 디자인도 재사용할 수 있습니다. 우리가 일상적으로 접하는 문제 중 상당수는 다른 많은 이들이 접
m.hanbit.co.kr
https://coding-factory.tistory.com/708
[Design Pattern] 디자인 패턴 정의와 종류에 대하여
소프트웨어 디자인 패턴이란? 소프트웨어 개발 방법으로 사용되는 디자인패턴(Desigin Pattern)은 과거의 소프트웨어 개발 과정에서 발견된 설계의 노하우를 축적하여 그 방법에 이름을 붙여서 이
coding-factory.tistory.com
- 자주 사용되는 디자인 패턴
1. 어댑터(Adapter) 패턴: OCP 적용
- 어댑터 == 변환기(Converter) == 서로 다른 두 인터페이스 간의 통신을 가능하게 하는 것
- 합성, 즉 객체를 속성으로 만들어 참조하는 디자인 패턴
※ 호출당하는 쪽의 메서드를 호출하는 쪽의 코드에 대응하도록 중간에 변환기를 두어 호출하는 패턴
2. 프록시(Proxy) 패턴: OCP, DIP 적용
- 대리자(Proxy)는 실제 서비스와 같은 이름의 메서드를 구현하며, 이때 인터페이스를 사용한다.
- 대리자는 실제 서비스에 대한 참조 변수를 갖는다.
- 대리자는 실제 서비스의 같은 이름을 가진 메서드를 호출한 후 그 값을 클라이언트에게 반환한다.
- 대리자는 실제 서비스의 메서드 호출 전후에 별도의 로직을 수행할 수 있다.
※ 제어 흐름을 조정하기 위한 목적으로 중간에 대리자를 두는 패턴
3. 데코레이터(Decorator) 패턴: OCP, DIP 적용
- 프록시 패턴과 구현 방법이 동일하지만, 클라이언트가 받는 반환값에 장식을 더한다.
→ 특징도 동일하다.
※ 메서드 호출의 반환값에 변화를 주기 위해 중간에 장식자를 두는 패턴
4. 싱글턴(Singleton) 패턴
- 싱글톤(singleton): 전체 프로그램에서 단 하나만 생성된 객체
1) 인스턴스를 생성할 수 없으므로 클래스 이름을 통해 정적 메서드를 호출하는 방식으로 객체를 얻는다.
2) 단일 객체인 경우 공유 객체로 사용되므로 속성을 갖지 않게 하는 것이 정석이다.
- 싱글톤 생성 방법
1) 클래스 외부에서 new 연산자로 생성자를 호출할 수 없도록 막는다.
→ 생성자 앞에 private 생성 제한자를 붙이면 된다.
2) 자신의 타입인 정적 필드를 하나 선언하고 자신의 객체를 생성해 초기화한다.
→ 클래스 내부에서는 new 연산자로 생성자 호출이 가능하다.
3) 정적 필드도 private 접근 제한자를 붙여 외부에서 필드값을 변경하지 못하도록 막는다.
4) 외부에서 호출할 수 있는 정적 메소드를 선언한 후 정적 필드에서 참조하고 있는 자신의 객체를 리턴한다.
→ 외부에서 객체를 얻는 유일한 방법: getInstance( ) 매소드 호출
※ 클래스의 인스턴스(객체)를 하나만 만들어 사용하는 패턴
5. 템플릿 메서드(Template Method) 패턴: DIP 적용
- 상위 클래스에는 공통 로직을 수행하는 템플릿 메서드를, 하위 클래스에는 오버라이딩을 강제하는 추상 메서드 혹은 선택적으로 오버라이딩 할 수 있는 훅(Hook) 메서드를 둔다.
※ 상위 클래스의 견본 메서드에서 하위 클래스가 오버라이딩한 메서드를 호출하는 패턴
6. 팩터리 메서드(Factory Method) 패턴: DIP 적용
- 팩터리 메서드: 객체를 생성하여 반환하는 메서드
※ 오버라이딩된 메서드가 객체를 반환하는 패턴
7. 전략(Strategy) 패턴: OCP, DIP 적용
- 구성 요소
1) 전략 메서드를 가진 전략 객체
2) 전략 객체를 사용하는 컨텍스트(사용자)
3) 전략 객체를 생성해 컨텍스트에 주입하는 클라이언트
- 템플릿 메서드 패턴과 유사하지만, 템플릿 메서드 패턴은 상속을, 전략 패턴은 객체 주입을 사용하므로, 클래스 다중 상속이 불가능한 자바에선 주로 전략 패턴이 사용된다.
※ 클라이언트가 전략을 생성한 후 실행할 컨텍스트에 주입하는 패턴
8. 템플릿 콜백(Template Callback) 패턴: OCP, DIP 적용
- 전략 패턴의 변형으로, 의존성 주입(DI)에서 사용하는 특별한 형태의 전략 패턴이다.
→ 전략을 익명 내부 클래스로 정의해서 사용하는 점을 제외하면 전략 패턴과 전부 동일하다.
- 템플릿 콜백 코드
public interface Strategy {
public abstract void runStrategy();
}
public class Soldier {
void runContext(Strategy strategy) {
System.out.println("전투 시작");
strategy.runStrategy();
System.out.println("전투 종료");
}
}
public class Client {
public static void main(String[] args) {
Soldier rambo = new Soldier();
rambo.runContext(new Strategy() {
@Override
public void runStrategy() {
System.out.println("총");
}
});
System.out.println();
rambo.runContext(new Strategy() {
@Override
public void runStrategy() {
System.out.println("칼");
}
});
System.out.println();
rambo.runContext(new Strategy() {
@Override
public void runStrategy() {
System.out.println("도끼");
}
});
}
}
- 리펙터링한 템플릿 콜백 패턴 코드(인터페이스 코드는 동일)
public class Soldier {
void runContext(String weaponSound) {
System.out.println("전투 시작");
executeWeapon(weaponSound).runStrategy();
System.out.println("전투 종료");
}
private Strategy executeWeapon(final String weaponSound) {
return new Strategy() {
@Override
public void runStrategy() {
System.out.println(weaponSound);
}
};
}
}
public class Client {
public static void main(String[] args) {
Soldier rambo = new Soldier();
rambo.runContext("총");
System.out.println();
rambo.runContext("칼");
System.out.println();
rambo.runContext("도끼");
}
}
→ 코드 참고: https://github.com/expert0226/oopinspring/tree/master/workspace_springjava/Chap06/src
※ 전략을 익명 내부 클래스로 구현한 전략 패턴
- 전략 패턴, 템플릿 콜백 패턴, 리팩터링된 템플릿 콜백 패턴을 제대로 이해하는 것이 중요하다.
'Spring > 자바 객체 지향의 원리와 이해' 카테고리의 다른 글
(Fin) 스프링 MVC를 이용한 게시판 구축 (X) (0) | 2023.09.12 |
---|---|
스프링 삼각형과 설정 정보 (0) | 2023.09.11 |
Mac STS Spring MVC Project 생성 오류 (0) | 2023.09.06 |
객체 지향 설계 5원칙 - SOLID (0) | 2023.09.04 |
댓글