[디자인패턴] 변화하는 것을 분리하자! (Strategy 전략패턴)
✅ 개요
애플리케이션의 요구사항은 계속해서 변한다.
오리가 수영하고, 소리를 낼 수 있다는 슈퍼클래스를 만들고
오리인형, 오리A, 오리B가 슈퍼클래스<오리>를 상속받도록 했다고 가정해보자.
다음 요구사항이 들어왔다.
오리가 날 수 있게 만들어줘
✍️ 상속을 사용하는것은 좋지 못할 수 있다.
슈퍼클래스<오라>에 Fly()를 추가하는 방법이 있다.
그러나 오리 인형이 <오리>를 상속받고 있기 때문에 사용할 수 없다.
(오리인형은 수영할 수 있지만, 날 수 없다.)
✍️ 인터페이스를 사용할 경우는?
Flyable이라는 인터페이스를 만들면 날아야만 하는 오리들에 대해서만 구현해주면 된다.
그러나 코드 중복을 무시할 수 없고, 날 수 있는 오리의 종류가 100가지가 넘어가게 되면 코드를 전부 고쳐주어야한다.
재사용에 유연한 코드를 작성할 수 없게된다.
상속과 인터페이스 모두 적절한 방법이아니다.
어떻게 하면 변경에 유연한 코드를 작성할 수 있을까?
이런 고민들은 선배개발자분들이 이미 다 겪었고,
나같은 초보 개발자는 디자인 패턴을 배워서 잘 적용하려고 노력하면 된다! ㅎㅎ
✅ 변화하는 것을 분리하자.
가장 중요한 기본 디자인 원칙은 다음과 같다.
⭐️⭐️⭐️⭐️⭐️
✔️ 바뀌는 부분은 따로 뽑아 캡슐화한다.
✔️ 나중에 바뀌지 않는 부분에는 영향이 없는 상태로 해당 부분을 고치거나 확장할 수 있다.
1️⃣ 바뀌는 부분은 무엇인가?
오리가 날다, 울다 : 문제가 발생할 수 있는 부분이다.
나머지(수영하다)는 문제가 되거나 자주 바뀌지 않는다.
이를 구분하는게 가장 먼저 해야할 일이다.
2️⃣ 바뀌는 부분에 대해 유연하게 만들어준다
오리 클래스는 수영하다를 갖고 있다.
오리 인스턴스를 새로 만들 때 오리의 행동을 동적으로 바꿀 수 있게 만든다.
1) 나는 행동과 우는 행동을 인터페이스로 만든다.
2) 나는 행동에 대해 필요한 구현체를 생성한다 >> 날개로 날다, 날지 않는다
3) 오리는 나는 행동을 갖게 되고, 어떤 구현체를 갖게 되는지 관심을 두지 않는다. (SOLID 중 의존관계 역전의 원칙!)
👩💻 생성자(Constructor)에서 구현체 설정
4) 오리A, 오리B와 같이 실제 오리 인스턴스는 생성될 때 구현체를 결정한다.
👩💻 세터(Setter)에서 구현체 설정
인형 오리는 날 수 없다. 따라서 FlyNoWay로 생성했다고 가정하자.
public class ModelDuck extends Duck {
public ModelDuck() {
flyBehavior = new FlyNoWay();
}
}
근데 인형 오리도 날 수 있는 방법이 새로 생겼다!
바로 인형 오리에 전기모터를 달면 인형 오리도 날 수 있다고 한다!!!
>>> 요구사항의 변화 : 인형 오리도 날 수 있게 변경할 것.
전기모터는 따로 구매할 수 있는 옵션이 되었고, 기존에 있던 제품들에도 붙힐 수 있다.
이런 경우 Setter를 이용해주어야한다.
4) 오리는 Setter 메서드를 추가함으로써 오리의 행동을 즉시 바꿀 수 있게 바꾼다.
public class ModelDuck extends Duck {
//기존 인형오리 생성자
public ModelDuck() {
flyBehavior = new FlyNoWay(); //기본적으로는 날 수 없게 생성
}
//Setter 추가
public void setFlyBehavior(FlyBehavior fb){
flyBehavior = fb;
}
}
//모터로 날기
public class FlyWithMotor implements FlyBehavior {
public void fly() {
System.out.println("모터를 달아서 날 수 있습니다.");
}
}
ModelDuck modelA = new ModelDuck();
modelA.performFly();
//날 수 없음
modelA.setFlyBehavior(new FlyWithMotor());
modelA.performFly();
//모터를 달아서 날 수 있습니다.
이렇게 생성자과 Setter를 통해 적절히 구현체를 설정해주면
변경에 유연한 객체지향적 설계가 가능해진다!
References
- Head First Design Patterns