728x90

e.g. SimUduck 구현

  • 맨 위 상위 클래스 Duck 으로 부터 상속 받는 하위 클래스 MallardDuck , RedheadDuck
Duck {
    quack()
    swim()
    display()
}
  • fly() 라는 메소드를 추가하고 일부 서브 클래스에서 해당 메서드를 구현해야한다.

 

  • 상위 클래스에 fly() 를 추가한다.
Duck {
    quack()
    swim()
    display()
    fly() // 새로 추가된 코드
}
  • 상속을 통한 해결
    • 하위 클래스에서도 모두 해당 메서드를 구현해야 하므로 해당 사항이 없는 클래스의 경우 아무런 행위를 하지 않도록 오버라이드한다.

 

  • 인터페이스 해결

💡 디자인 원칙 1
바뀌는 부분은 따로 뽑아서 캡슐화한다. 그러면 나중에 바뀌지 않는 부분에는 영향을 미치지 않고 그 부분만 고치거나 확장할 수 있다.

  • ‘변화하는 부분’과 ‘그대로 있는 부분’ 분리하기
    • fly() / quack() Duck 클래스로부터 오리 종류에 따라 달라지도록 분리하고 클래스 집합을 새로 만든다.

 

💡 디자인 원칙 2
구현보다는 인터페이스에 맞춰서 프로그래밍한다.
= 상위 형식에 맞춰서 프로그래밍 한다.
= 변수를 선언할 때 보통 추상 클래스나 인터페이스 같은 상위 형식으로 선언해야한다. 객체를 변수에 대입할 때 상위 형식을 구체적으로 구현한 형식이라면 어떤 객체든 넣을 수 있기 때문이다. 그러면 변수를 선언하는 클래스에서 실제 객체의 형식을 몰라도 된다.

  • 각 행동은 인터페이스(FlyBehavior, QuackBehavior)로 표현하고 이런 인터페이스를 사용해서 행동을 구현한다.
  • ⚡ 더이상 Duck 클래스에서 구현하지 않는다.

 

  • 나는 행동과 꽥꽥거리는 행동을 Duck 클래스에서 정의한 메소드를 써서 구현하지 않고 다른 클래스에 위임한다.

🔠 인터페이스(interface)
- 자바의 구조
- 자바 키워드 → 개념 자체

 

  • Duck 클래스
FlyBehavior flyBehavior
QuackBehavior quackBehavior
// 행동 변수를 위한 행동 인터페이스 형식 선언
// 인스턴스 변수 실행 시에는 특정 행동의 레터런스가 저장이 된다.

performQuack()
swim()
display()
performFly()

 

public abstract class Duck {
    QuackBehavior quackBehavior;

    ...

    public void performQuack() {
        quackBehavior.quack();
    }
}

 

public class MallarDuck extends Duck {
    public MallarDuck() {
        // quackBehavior이 호출되면 꽥꽥거리는 행동은 객체에게 위임된다.
        quackBehavior = new Quack(); 
        flyBehavior = new FlyWithWings();
    }

    public void display() {
        System.out.println("저는 물오리입니다.");
    }
}
  • Duck 으로 부터 상속받은 quackBehavior 인스턴스 변수에 Quack 형식의 새로운 인스턴스를 대입한다.
  • MallarDuckDuck 으로 부터 상속받은 flyBehavior 인스턴스 변수에 FlyWithWing 의 새로운 인스턴스를 대입한다.

 

public abstract class Duck {
    // 레퍼런스 변수 2개를 선언
    // 같은 패키지에 속하는 모든 서브 클래스에서 해당 변수를 상속받음

    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public Duck() { }

    public abstract void display();

    public void performFly() {
        flyBehavior.fly();
    }

    public void performQuack() {
        quackBehavior.quack();
    }

    public void swim() {
        System.out.println("모든 오리는 물에 뜹니다. 가짜 오리도 뜨죠.");
    }

}
728x90