내용을 정리한 글은 워낙 많아서 깨달음을 얻은 부분 위주로 정리했다.
전략패턴 특징
- 오브젝트를 아예 둘로 분리하고 클래스 레벨에서는 인터페이스를 통해서만 의존하도록 만드는 패턴
- GoF의 디자인 패턴 책에서는 전략 패턴을 다음과 같이 정의한다.
동일 계열의 알고리즘군을 정의하고 → 전략 구현체로 정의하고
각각의 알고리즘을 캡슐화하여 → 인터페이스로 추상화
이들을 상호 교환이 가능하도록 만든다. → 합성(composition)으로 구성
알고리즘을 사용하는 클라이언트와 상관없이 독립적으로 → 컨텍스트 객체 수정 없이
알고리즘을 다양하게 변경할 수 있게 한다. → 메서드를 통해 전략 객체를 실시간으로 변경함으로써 전략 변경
- 쉽게 말하면 객체지향의 기법인 SOLID 원칙과 합성, 다형성, 캡슐화 등 OOP 기술들의 총 집합 버전이다.
- But, 알고리즘이 많아질수록 관리해야 할 객체의 수가 늘어난다는 단점이 있다.
전략패턴을 적용한 코드 (코드 출처)
// 전략 - 추상화된 알고리즘
interface Weapon {
void offensive();
}
class Sword implements Weapon {
@Override
public void offensive() {
System.out.println("칼을 휘두르다");
}
}
class Shield implements Weapon {
@Override
public void offensive() {
System.out.println("방패로 밀친다");
}
}
class CrossBow implements Weapon {
@Override
public void offensive() {
System.out.println("석궁을 발사하다");
}
}
// 컨텍스트 - 전략을 등록하고 실행
class TakeWeaponStrategy {
Weapon wp;
void setWeapon(Weapon wp) {
this.wp = wp;
}
void attack() {
wp.offensive();
}
}
// 클라이언트 - 전략 제공/설정
class User {
public static void main(String[] args) {
// 플레이어 손에 무기 착용 전략을 설정
TakeWeaponStrategy hand = new TakeWeaponStrategy();
// 플레이어가 검을 들도록 전략 설정
hand.setWeapon(new Sword());
hand.attack(); // "칼을 휘두르다"
// 플레이어가 방패를 들도록 전략 변경
hand.setWeapon(new Shield());
hand.attack(); // "방패로 밀친다"
// 플레이어가 석궁을 들도록 전략 변경
hand.setWeapon(new Crossbow());
hand.attack(); // "석궁을 발사하다"
}
}
DI는 무조건 인터페이스를 둬야 하는가?
- 인터페이스를 사이에 둬서 클래스 간의 의존관계가 고정되지 않게 하고, 런타임 시에 의존할 오브젝트와의 관계를 다이내믹하게 주입하는 것이 맞다.
- 따라서 인터페이스를 사용하지 않았다면 엄밀히 말해서 온전한 DI라고 볼 수 없다.
- But, 스프링의 DI는 객체의 생성과 관계설정에 대한 제어권한을 오브젝트에서 제거하고 외부로 위임했다는 IoC 개념을 포괄한다.
- 그러므로 JdbcContext를 UserDao 객체가 사용하도록 주입했다는 건 DI의 기본을 따르고 있는 것이다.
- 인터페이스가 없다는 건 그만큼 두 객체가 긴밀한 관계를 맺고 있음을 의미한다. 즉, 강한 응집도를 갖고 있다.
템플릿/콜백 패턴
- 전략 패턴의 확장판으로 보면 된다.
- 복잡하지만 바뀌지 않는 일정한 패턴을 갖는 작업 흐름이 존재하고, 그중 일부분만 바꿔서 사용해야 하는 경우에 적합한 패턴이다.
- 전략 패턴의 컨텍스트를 템플릿이라 부르고, 익명 내부 클래스로 만들어지는 오브젝트를 콜백이라고 부른다.
- 콜백은 템플릿 안에서 호출되는 것으로 만들어진 오브젝트를 의미한다.
- 콜백은 일반적으로 하나의 메서드를 가진 인터페이스를 사용한다. (이를 함수형 인터페이스라고 부른다.)
- 콜백 엔터페이스의 메서드에는 대부분 파라미터가 있다. 해당 파라미터는 템플릿의 작업 흐름 중에 만들어지는 컨텍스트 정보를 전달받을 때 사용된다.
전략 패턴 vs. 템플릿/콜백 패턴
- 간단한 전략 알고리즘일 경우 굳이 전략 팩토리 객체를 정의하여 코드 라인수만 차지할 필요가 전혀 없다.
- 템플릿 콜백 패턴으로 변환해 주면, 클라이언트에서 바로 익명 클래스 혹은 람다함수로 알고리즘 로직 코드를 정의한 뒤 매개변수로 주입만 시켜주면 된다.
참고
'Book > 토비의 스프링' 카테고리의 다른 글
[토비의 스프링] 다이내믹 프록시를 이해해보자 (0) | 2024.04.23 |
---|---|
[토비의 스프링] 4장 예외 (0) | 2024.04.18 |
[토비의 스프링] 2장 테스트 (0) | 2024.04.16 |
[토비의 스프링] 1장 오브젝트와 의존관계 (0) | 2024.04.16 |