깃허브 코드
알고리즘 군을 정의하고 캡슐화해서 각각의 알고리즘 군을 수정해서 쓸 수 있게 해줍니다. 전략 패턴을 사용하면 클라이언트로부터 알고리즘을 분리해서 독립적으로 변경할 수 있습니다.
알고리즘 군을 정의하고 캡슐화해서 각각의 알고리즘 군을 수정해서 쓸 수 있게 해줍니다. 전략 패턴을 사용하면 클라이언트로부터 알고리즘을 분리해서 독립적으로 변경할 수 있습니다.

새로운 Duck과 기존의 Duck의 꽥꽥 소리와 나는 기능을 각기 다르게 적용하고 싶은데
기존 Duck의 서브클래스는 같은 꽥 소리를 내고, 똑같이 날 수 밖에 없습니다.
MallardDuck : quack() X, fly() O
ReadHeadDuck : quack() O, fly() X
RubberDuck : quack() O (삐삐 소리 내야함), fly() X

ex)
public class MallardDuck extends Duck {
public MallardDuck() {
quackBehavior = new MuteQuack();
flyBehavior = new FlyWithWings();
}
@Override
public void display() {
System.out.println("mallard duck 입니다");
introduce();
}
}

신문사 + 구독자 = 옵저버 패턴
(신문사는 주제, 구독자는 옵저버)
주제에서는 중요한 데이터를 관리하는데 데이터가 바뀌면 옵저버들에게 그 소식이 전달됩니다.한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다 의존성을 정의

WeaterData는 온도, 습도, 기압 기상 관측값이 갱신될 때마다 measurementsChanged()
메소드를 호출해서 다른 인스턴스에 업데이트 해줍니다.
public void measurementsChanged() {
float temperature = getTemperature();
float humidity = getHumidity();
float pressure = getPressure();
concurrentConditionsDisplay.update(temperature, humidity, pressure);
statisticsDisplay.update(temperature, humidity, pressure);
forecastDisplay.update(temperature, humidity, pressure);
}

public class WeatherData implements Subject {
List<Observer> observers = new ArrayList<>();
float temperature;
float humidity;
float pressure;
public WeatherData() {}
public float getTemperature() {
return 32;
}
public float getHumidity() {
return 50;
}
public float getPressure() {
return 29;
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements() {
this.temperature = getTemperature();
this.humidity = getHumidity();
this.pressure = getPressure();
System.out.println();
measurementsChanged();
}
}
public class ForecastDisplay implements Observer, Display {
public float temperature;
public float humidity;
public float pressure;
public ForecastDisplay() {
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
display();
}
@Override
public void display() {
System.out.println();
System.out.println("Forecast Display");
System.out.println("Temperature: " + temperature);
System.out.println("Humidity: " + humidity);
System.out.println("Pressure: " + pressure);
System.out.println();
}
}

객체들이 상호작용할 수 있지만, 서로를 잘 모르는 관계
객체 사이의 상호의존성 최소화 -> 유연성이 좋아짐
객체에 추가 요소를 동적으로 더할 수 있습니다. 데코레이터를 사용하면
서브클래스를 만들 때보다 훨씬 유연하게 기능을 확장할 수 있습니다.

각각의 옵션을 단 메뉴들을 일일이 객체로 만들어주는 상황

public abstract class Beverage { // 음료
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
public class Espresso extends Beverage {
public Espresso() {
this.description = "Espresso";
}
@Override
public String getDescription() {
return "Espresso";
}
@Override
public double cost() {
return 3000;
}
}
public abstract class CondimentDecorator extends Beverage { // 첨가물
Beverage beverage;
public abstract String getDescription();
}
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
@Override
public double cost() {
return beverage.cost() + 1500;
}
}
Beverage espresso = new Espresso();
espresso = new Whip(espresso);
System.out.println(espresso.getDescription() + " " + espresso.cost() + "원");
Beverage beverage = new HouseBlend();
beverage = new Mocha(beverage);
beverage = new Whip(beverage);
System.out.println(beverage.getDescription() + " " + beverage.cost() + "원");
