Java/Design Pattern

[헤드퍼스트 디자인 패턴] 1. 전략 패턴

noahkim_ 2024. 12. 16. 03:10

에릭 프리먼 님의 "헤드퍼스트 디자인 패턴" 책을 정리한 포스팅 입니다

 

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("삑삑"); }
}
  • 해당 인터페이스의 구현체(알고리즘군)를 미리 생성
  • 다른 형식의 객체에서도 행동을 재사용할 수 있음