깃허브 코드
알고리즘 군을 정의하고 캡슐화해서 각각의 알고리즘 군을 수정해서 쓸 수 있게 해줍니다. 전략 패턴을 사용하면 클라이언트로부터 알고리즘을 분리해서 독립적으로 변경할 수 있습니다.
알고리즘 군을 정의하고 캡슐화해서 각각의 알고리즘 군을 수정해서 쓸 수 있게 해줍니다. 전략 패턴을 사용하면 클라이언트로부터 알고리즘을 분리해서 독립적으로 변경할 수 있습니다.
새로운 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() + "원");