에릭 프리먼 님의 "헤드퍼스트 디자인 패턴" 책을 정리한 포스팅 입니다
1. 오리 시뮬레이션 게임
- Duck 클래스를 슈퍼클래스로 생성
- 각 오리 종류를 서브클래스로 두어 상속을 활용함 (MallardDuck, RedheadDuck, RubberDuck)
심각한 문제 발생
- 슈퍼클래스에 추상메서드 추가 시, 모든 서브클래스에서 구현이 강제됨
- 몇몇 서브클래스에만 적용되어야 할 메서드일 경우, 논리적으로 오류가 발생함
ex: fly() 추가
- MallardDuck, RedheadDuck에는 가질 수 있는 행동
- RubberDuck에는 가져서는 안되는 행동
상속 생각하기
- 해당 메서드를 구현할 서브클래스는 구현하고, 나머지는 공백으로 오버라이딩 해두기
- 결국 모든 서브클래스에서 해당 메서드를 구현해야 해서, 올바른 방법이 아님
인터페이스 설계하기
상속의 단점
- 모든 서브클래스에서 구현해야 함
- 규격이 바뀔 경우 서브클래스에서 계속해서 구현해줘야 함
공통적으로 구현해야 하는 명세만 인터페이스로
- 상속의 단점을 해결함
- 그러나, 코드를 재사용하지 않아 코드 관리가 어려움
2. 디자인 원칙
캡슐화
public abstract class Duck {
QuackBehavior quackBehavior;
public void performQuack() { quackBehavior.quack(); }
public void setQuackBehavior(QuackBehavior quackBehavior) { this.quackBehavior = quackBehavior; }
}
- 달라지는 부분을 찾아서 달라지지 않는 부분과 분리하기
- 유연성 향상 (바뀌지 않는 부분에 영향이 미치지 않음)
인터페이스 타입 인자
- 명세를 따르는 인터페이스의 참조변수를 여러 구현체에 할당할 수 있음 (다형성)
Composition
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
// ...
}
- 두 클래스를 합치는 것
setter로 행동 받기
- 동적으로 행동 지정 가능
명세화
public interface QuackBehavior {
void quack();
}
- 달라지는 부분을 인터페이스로 만듬
- 인터페이스에 행동을 위임함
Strategy
public class Quack implements QuackBehavior {
@Override
public void quack() { System.out.println("꽥꽥"); }
}
public class Squeak implements QuackBehavior {
@Override
public void quack() { System.out.println("삑삑"); }
}
- 해당 인터페이스의 구현체(알고리즘군)를 미리 생성
- 다른 형식의 객체에서도 행동을 재사용할 수 있음
'Java > Design Pattern' 카테고리의 다른 글
[헤드퍼스트 디자인 패턴] 5. 싱글턴 패턴 (1) | 2024.12.16 |
---|---|
[헤드퍼스트 디자인 패턴] 4. 팩토리 패턴 (0) | 2024.12.16 |
[헤드퍼스트 디자인 패턴] 3. 데코레이터 패턴 (1) | 2024.12.16 |
[헤드퍼스트 디자인 패턴] 2. 옵저버 패턴 (0) | 2024.12.16 |
[헤드퍼스트 디자인 패턴] 0. 디자인 패턴이란 (1) | 2024.12.16 |