각 오리마다 '우는 행위(quack)'과 '나는 행위(fly)'가 다르다. 이를 전략 인터페이스로 빼내어 전략에 대한 추가에 열려있게 하면서, 기존 오리 클래스(파생 클래스)에 대한 수정 혹은 불필요한 코드 중복을 줄였다.
클래스 다이어그램과 코드는 아래와 같다.
// Duck class
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {
}
// 구체적인 fly 행위 인스턴스를 인자로 전달한다. => 구체적인 fly 방식을 설정
public void setFlyBehavior(FlyBehavior fb) {
flyBehavior = fb;
}
// 구체적인 quack 행위 인스턴스를 인자로 전달한다. => 구체적인 quack 방식을 설정
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}
abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("All ducks float, even decoys!");
}
}
// 고무 오리 클래스 예시
public class RubberDuck extends Duck {
public RubberDuck() {
flyBehavior = new FlyNoWay(); // 날기 기능: 날 수 없음
quackBehavior = new Squeak(); // 우는 기능: 쥐 우는 소리
}
public void display() { // 추상메서드 구현
System.out.println("I'm a rubber duckie");
}
}
main (클라이언트)
public class MiniDuckSimulator {
public static void main(String[] args) {
MallardDuck mallard = new MallardDuck();
RubberDuck rubberDuckie = new RubberDuck();
DecoyDuck decoy = new DecoyDuck();
mallard.performQuack();
rubberDuckie.performQuack();
decoy.performQuack();
Duck model = new ModelDuck();
// setter을 통해 '로켓 날기' 행위 주입
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
모든 오리는 수영을 하기에 상위 클래스(Duck)에 swim()을 구현하였다
=> code reuse
그러나 모든 오리에게서 보이는 모습은 다르다. display()라는 추상 메서드를 정의한다.
=> push to implements, 특성상 강요의 의미. 이는 자손 클래스에서의 구현을 강요하는 것이다.
- Inheritance: "code reuse(재사용)"
- Realization: "push to implements(자손 클래스에 구현을 맡김)"
- Override: "refused bequest(조상으로부터 내려온 메서드 거부, 자신만의 알고리즘으로..)"