티스토리 뷰
의존하는 객체가 자주 변하는 경우
Soldier(군인)이라는 클래스와 Gun(총)이라는 클래스가 있고, Soldier클래스는 Gun클래스를 의존하고 있다고 가정해봅시다. 이런 경우를 코드로 간략하게 나타내면 아래와 같습니다.
class Soldier{
. . .
Gun gun = new Gun();
. . .
}
하지만 Soldier입장에서, 사용하는 무기가 Gun이 아닌 다른 경우가 존재 할 수 도 있습니다. 예를 들어, Sword(검)이라던지, Bow(활) 같은 경우입니다. 그럼 매번 의존하는 무기가 변경 될 때 마다 코드를 변경 해주어야 합니다.
- Soldier의 무기가 Sword로 변경 되어야 하는 경우
class Soldier{ . . . Sword sword = new Sword(); . . . }
- Soldier의 무기가 Bow로 변경 되어야 하는 경우
class Soldier{ . . . Bow bow = new Bow(); . . . }
무기의 종류가 바뀔 때 마다, Solider 클래스의 수정이 수반 되어야 합니다. 이런 경우 전략 패턴을 적용하게 되면 Solider의 코드 변경 없이 다른 무기를 의존하게 할 수 있습니다.
각 무기들이 공통된 메소드만을 가지고 있을 때, 이를 Weapon(무기)라는 인터페이스로 두고 각 무기들은 Weapon을 구현한 클래스로 만들 수 있습니다. 이런식으로 구현하면 Soldier 입장에서 참조 타입을 Weapon으로 받을 수 있습니다.
class Soldier{
. . .
Weapon weapon = new Gun(); //생성자는 잠시 잊어주세요.
. . .
}
전략 패턴
위와 같은 디자인 패턴을 전략 패턴이라고 합니다. 그림으로 나타내면 아래와 같습니다.
Conext는 Strategy라는 인터페이스를 의존하고, Starategy 인터페이스를 구현한 여러 클래스들이 있습니다. Context 입장에서는 Strategy(전략) 들이 여러개의 클래스 일지라도, Strategy 인터페이스를 구현한 경우라면 의존을 변경하기 쉽습니다. 전략 패턴은 객체지향의 5대 설계 원칙 중 DIP (의존 역전 법칙)을 설명하기에도 적절합니다. DIP 설계 원칙을 준수함으로써 객체의 결합도를 낮추고 유지보수의 이점을 갖을 수 있습니다.
Client 객체
하지만 실제 코드에는 Gun()이라는 클래스의 생성자가 들어가기 때문에, 자주 바뀌는 무기로부터 완전히 코드가 자유롭지는 못합니다. 이를 해결 하기 위해서 Weapon 객체를 생성하고 Soldier에게 전달 해주는 Client 객체를 따로 만들어 줍니다. (Client 객체라는 건 전략 패턴에서만 쓰이는 키워드는 아닙니다.)
class Client{
. . .
Weapon weapon = new gun();
Soldier soldier = new Soldier(weapon);
}
class Soldier{
private Weapon weapon;
public Soldier(Weapon weapon){
this.weapon = weapon;
}
}
이런 식으로 객체를 생성하고 의존 관계를 주입하는 객체가 별도로 존재 한다면 Soldier는 무기를 직접 생성 하지 않고 외부로 부터 주입만 받게 됩니다. 이젠 Soldier의 코드 수정 없이 의존하는 무기들을 변경 할 수 있습니다! 스프링의 의존 주입은 이러한 전략 패턴을 사용하여서 구현 되었습니다.
참고도서
-스프링 입문을 위한 자바 객체지향의 원리와 이해 (저자 김종민)
-토비의 스프링 3.1 (저자 이일민)
'Design Pattern' 카테고리의 다른 글
LSP(리스코프 치환 원칙) - 오리와 오리장난감은 진짜 LSP 위반일까? (0) | 2019.11.17 |
---|---|
템플릿/콜백 패턴이란? (1) | 2019.04.01 |
객체 설계의 응집도란? (2) | 2019.01.15 |
객체지향의 4대 특성 (2) | 2018.12.31 |
객체의 추상화 (Abstraction) (0) | 2018.12.04 |