2. Duck
quack()
swim()
display()
// other duck methods
MallardDuck
display()
// looks like mallard
RedheadDuck
display()
// looks like redhead
Other duck
types
초기 모델
Mallard Duck: 천둥오리
3. 고객 요구 사항 : 오리를 날아 다니게 해주세요…
수정모델
Duck
quack()
swim()
display()
fly()
// other duck methods
MallardDuck
display()
RedheadDuck
display() Other duck
types
4. 수정 모델의 문제점…
Duck
quack()
swim()
display()
fly()
// other duck methods
MallardDuck
display()
// looks like mallard
RubberDuck
상속받은 모든 오리들에게 행동이 적용이 됨
불필요한 행동들은 모드 오버라이딩 해야 함
quack()
//overridden to squeak
display()
// looks like rubberduck
fly()
// override to do nothing
RedheadDuck
display()
// looks like redhead
Rubber Duck : 고무오리
5. 그렇다면 인터페이스는 어떨까?
Duck
swim()
display()
// other duck methods
MallardDuck
display()
fly()
quack()
Quackable
quack()
Flyable
fly()
RedheadDuck
display()
fly()
quack()
RubberDuck
display()
quack()
DecoyDuck
display()
Interfaces
모든 코드에 중복이 생김
코드 관리가 힘들어짐
=>빈대 잡으려다 초가삼간 날린 격
fly() 안의 내용이 같아도 오리마다 중복으로 코드를 생성해 줘야 함
6. 디자인 원칙 1 : 애플리케이션에서 달라지는 부분을 찾아내고, 달라지지 않는 부분으로부터 분리시킨다.
바뀌는 부분
Duck
Behaviors
바뀌지 않는 부분
Duck
swim()
display()
fly()
quack()
바뀌지 않는 부분
바뀌는 부분
7. 그럼 실제적으로 어떻게 구현할까?
각 행동을 인터페이스로 표현하고 행동을 구현할 때 이런 인터페이스를 구현하도록….
그러니까 어떻게 구현하냐고….?
나는 행동과 꽥꽥거리는 행동은 Duck 클래스 에서 구현하지 않습니다.
특정행동만을 목적으로 하는 클래스 집합을 만듭니다.
행동(behavior) 인터페이스는 Duck 클래스가 아닌, 행동 클래스에서 구현합니다.
무슨 차인데요?
Dcuk 클래스에서 구체적으로 구현하든 서브 클래스에서 구현하든 둘 다 특정 구현에 의
존했고 이에 따라 행동을 변경할 여지가 없음
새로운 디자인은 Duck의 서브클래스에서 인터페이스로 표현된 행동을 사용
따라서 행동을 실제로 구현한 것( FlyBehavior , QuickBehavior를 구현하는 클래스에 코딩
되어 있는 행동) 은 Duck 서브 클래스에 국한되지 않음
8. <<interface>>
FlyBehavior
fly()
FlyWithWings
fly(){
// implements duck
flying
}
<<interface>>
QuackBehavior
quack()
Quack
quack(){
// implements duck
quacking
}
FlyNoWay
fly(){
// do nothing –
Can’t fly
}
Squeak
MuteQuack
quack(){
// do nothing –
Can’t quack
}
quack(){
// implements duck
squeak
}
Mute : 음소거
이런 디자인의 장점 :
Duck 외의 다른 객체에서도 FlyBehavior, QuackBehavior를 사용할 수 있음
기존 행동 클래스를 수정하지 않고 새로운 행동을 추가할 수 있음
디자인 원칙 2 : 구현이 아닌 인터페이스에 맞춰서 프로그래밍 한다.
9. 구현이 아닌 인터페이스에 맞춰서 프로그래밍 한다는 게 뭔가요?
실제 실행시에 쓰이는 객체가 코드에 의해서 고정되지 않도록,
어떤 상위 형식에 맞춰서 프로그래밍 함으로써 다형성을 활용해야 한다는 것
구현에 맞춰서 프로그래밍을 한 예)
Dog d = new Dog();
d.bark();
인터페이스에 맞춰서 프로그래밍을 한 예)
Animal animal = new Dog();
animal.makesound();
더 바람직한 방법 예)
a = getAnimal();
a.makeSound();
Dog
makeSound(){
bark()
}
bark() { //짖음}
Animal
makeSound()
Cat
makeSound(){
meow();
}
meow(){ //야옹 소리 냄}
10. Duck
Behaviors
Duck
FlyBehavior: flyBehavior
QuackBehavior: quackBehavior
performFly()
swim()
display()
performQuack()
//other duck-like methods
Duck 행동 통합하기….
public class Duck{
QuackBehavior quackBehavior;
public void performQuack() {
quackBehavior.quack();
}
}
11. 큰 그림으로 바라봅시다….
MallardDuck
display()
RedHeadDuck
display()
RubberDuck
display()
DecoyDuck
display()
Duck
FlyBehavior: flyBehavior
QuackBehavior: quackBehavior
performQuack()
performFly()
setFlyBehavior()
setQuackBehavior()
swim()
display()
<<interface>>
FlyBehavior
fly()
FlyWithWings
fly()
// implements duck
flying
FlyNoWay
fly()
// do nothing –
Can’t fly
<<interface>>
QuackBehavior
quack()
Quack
quack()
// implements
duck
quacking
Squeak
quack()
// implements
squeak
Mutequack
quack()
// do nothing
이렇게 두 클래스를 합치는 것을 구성(composition)을 이용하는 것 이라고 부름
12. 디자인 원칙 3 : 상속 보다는 구성을 활용한다.
구성을 이용하여 시스템을 만들면 유연성을 향상 시킬 수 있음.
스트래티지 패턴 (Strategy Pattern)
알고리즘군을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있도록 만든다.
스트래티지을 활용하면 알고리즘을 사용하는 클라이언트와는 독립적으로 알고리즘을 변경할 수 있다.