
같은 종류의 작업을 하는 알고리즘을 정의
각 알고리즘을 캡슐화, 그리고 알고리즘들을 서로 바꿔 사용할 수 있도록 함
→ 모든 알고리즘이 동시에 사용되는 것이 아니면 굳이 함께 넣어야 할 필요 없음
알고리즘을 런타임때 선택할 때 필요한 패턴
ex) 카메라 앱 필터: 카메라 앱에 모두 내장시킬 필요는 없음
→ 필터 추가할 때 전체를 업데이트 vs 필터만 추가




public class Duck {
    //인터페이스를 가지고 있음
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
    public void performFly(){
        flyBehavior.fly();
    }
    public void performQuack(){
        quackBehavior.quack();
    }
    public void display(){
        System.out.println("display");
    }
}
public class MallardDuck extends Duck {
    public MallardDuck(){
        setQuackBehavior(new Quack()); //상황에 맞는 객체 생성해서 넣음
        setFlyBehavior(new FlyWithWings());
    }
    @Override
    public void display() {
        System.out.println("mallard Duck");
    }
}

1. 바뀌는 부분: recipe 분리 -> interface
2. interface 구현
public interface CookRecipe {
    public void cook();
}
public class CheeseRecipe implements CookRecipe{
    @Override
    public void cook() {
        System.out.println("CheeseRecipe");
    }
}
3. Context 구현 = interface를 멤버 필드로 가지는 객체 생성
: interface 구현체의 함수 호출하는 메소드 추가, interface는 setter로 변경 가능
public class Ramen {
    private CookRecipe cookRecipe;
    //변경이 가능하도록 함
    public void setCookRecipe(CookRecipe cookRecipe) {
        this.cookRecipe = cookRecipe;
    }
    public void performCook(){
        cookRecipe.cook();
    }
}
4. main
public class main {
    public static void main(String[] args) {
        Ramen r = new Ramen();
        r.setCookRecipe(new CheeseRecipe());
        r.performCook();
    }
}