SimDuck 예제
26 Mar 2022- SimDuck 응용 프로그램 시작
![]() |
|---|
| 그림1 |
- 오리들이 날아 다닐 수 있도록 변경
![]() |
|---|
| 그림2 |
- 그런데 심각한 문제가 생겼습니다.
![]() |
|---|
| 그림3 |
Duck 수퍼 클래스에 fly가 추가 되면서 모든 서브 클래스들이 날 수 있게 되는 문제가 발생
프로그램 한 부분의 변경으로 프로그램 전체에 부작용이 발생(날아 다니는 고무 오리)
- 상속에 대해 생각해 봅시다
소리를 내지 않거나 날 수 없을 경우 quack과 fly 메소드를 override하면 될까?
Duck의 행동을 제공하는 데 있어 상속을 사용할 경우 아래와 같은 단점이 발생 한다
- 서브 클래스에서 코드가 중복 된다.
- 실행시 특징을 바꾸기 어렵다
- 모든 오리의 행동을 알기 어렵다.
- 코드를 변경 했을 때 다른 오리들 한테 원치 않는 영향을 끼칠 수 있다.
- 서브 클래스에서 코드가 중복 된다.
![]() |
|---|
| 그림4 |
- 인터페이스는 어떨까?
![]() |
|---|
| 그림5 |
모든 서브 클래스에 날거나 꽥꽥거리는 기능이 있어야 하는 것은 아니므로 상속을 사용하는 것이 올바른 해결책이 아니라는 것은 알 수 있다.
서브 클래스에서 Flyable, Quackable을 구현하도록 함으로써 일부 문제점은 해결할 수 있지만,
그렇게 하면 그러한 행동에 대한 코드 재사용을 전혀 기대할 수 없기 때문에 코드 관리 면에서 문제점을 야기한다.
날아가는 동작을 조금 변경하기 위해 날아 다닐 수 있는 서브 클래스 전체를 고쳐야 할 수 있다.
- 문제를 명확하게 파악하기
디자인 원칙
애플리케이션에서 달라지는 부분을 찾아내고, 달라지지 않는 부분으로 부터 분리 시킨다. 바뀌는 부분은 따로 뽑아서 캡슐화 시킨다. 그렇게 하면 나중에 바뀌지 않는 부분에는 영향을 주지 않은 채로 그 부분만 고치거나 확장할 수 있다.
-
바뀌는 부분과 그렇지 않은 부분 분리하기
- fly()와 quack()은 Duck 클래스에서 오리 마다 달라지는 부분입니다.
-
이러한 행동을 Duck 클래스에서 분리하여 각각의 행동을 나타내는 클래스 집합을 만듭니다.
- 오리의 행동 디자인
디자인 원칙
구현이 아닌 인터페이스에 맞춰서 프로그래밍 한다.
각 행동은 인터페이스로 표현하고 행동을 구현할 때 이런 인터페이스를 구현하도록 한다.
인터페이스에 맞춰서 프로그래밍한다는 것은 사실 상위 형식에 맞춰서 프로그램밍한다는 것을 뜻합니다.
- Duck의 행동을 구현하는 방법
FlyBehavior와 QuackBehavior라는 두 인터페이스를 사용합니다.
![]() |
|---|
| 그림6 |
- Duck 행동 통합하기
가장 중요한 점은 나는 행동과 꽥꽥 소리를 내는 행동을 Duck 클래스에서 정의한 메소드를 써서 구현하지 않고 다른 클래스에 위임한다는 것이다.
![]() |
|---|
| 그림7 |
- “A는 B이다” 보다 “A에는 B가 있다”가 나을 수 있다.
디자인 원칙
상속 보다는 구성을 활용 한다.
“A에는 B가 있다” 관계에 대해 생각해 봅시다.
각 오리에는 FlyBehavior와 QuackBehavior가 있으며, 나는 행동과 꽥꽥 거리는 행동을 위임 받습니다.
두 클새스를 이런 식으로 합치는 것을 구성을 이용하는 것이라고 부릅니다.
오리 클래스에서는 행동을 상속 받는 대신, 올바른 행동 객체로 구성됨으로써 행동을 부여 받게 됩니다.
이 테크닉은 매우 중요한 테크닉입니다.
구성을 이용하여 시스템을 만들면 유연성을 크게 향상시킬 수 있습니다.
단순히 알고리즘군을 별도의 클래스의 집합으로 캡슐화할 수 있도록 만들어 주는 것 뿐 아니라
구성요소로 사용하는 객체에서 올바른 행동 인터페이스를 구현하기만 하면 실행시에 행동을 바꿀 수도 있게 해 줍니다.
- 스트레티지 패턴
알고리즘군을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있도록 만든다.
스크래티지를 활용하면 알고리즘을 사용하는 클라이언트와는 독립적으로 알고리즘을 변경할 수 있다.






