A. 인터페이스가 아닌 구체적인 구현을 바탕으로 코딩함.
B. 새로운 디스플레이 항목이 추가될 때마다 코드를 변경해야 함.
C. 실행 중에는 디스플레이 항목을 추가하거나 제거할 수 없음.
E. 바뀌는 부분을 캡슐화하지 않음.
p.78
public interface DisplayElement {
public void display();
}
public interface Observer {
public void update();
//기상 정보가 변경되었을 때 옵저버에게 전달되는 상태값들.
//이 인터페이스는 모든 옵저버 클래스에서 구현되어야 함. 그래서 모든 옵저버들은 update() 메소드를 구현해야 한다.
}
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
//위 두 메소드들은 Observers을 인자로 받음. 각각 옵저버를 등록하거나 제거하는 역할.
public void notifyObservers();
//주제의 상태가 변경되었을 때 모든 옵저버에게 변경 내용을 알리려고 호출되는 메소드.
}
public class WeatherData implements Subject{
//인스턴스 변수 선언
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData(){
observers = new ArrayList<Observer>();
}
//Subject 인터페이스를 구현하는 부분
public void registerObserver(Observer o){//옵저버가 둥록 요청 시 목록 맨 뒤에 추가하기만 하면 됨
observers.add(o);
}
public void removeObserver(Observer o){//옵저버가 탈퇴 요청 시 목록에서 빼기만 하면 됨
observers.remove(o);
}
public void notifyObserver(){
for(Observer observer : observers){
observer.update();
}
}
/* 중요한 부분 - 모든 옵저버에게 상태 변화를 알려줌*/
// 모두 Observer 인터페이스를 구현하는 update() 메소드가 있는 객체들이므로 상태 변화를 쉽게 알려줄 수 있음.
public void measurementsChanged(){
//가상 스테이션으로부터 갱신된 측정 값을 받으면 옵저버들에게 알림.
notifyObserver();
}
public void setMeasurements(float temperature, float humidity, float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
public class CurrentConditionsDisplay implements Observer, DisplayElement{
// Observer - WeatherData 객체로부터 변경 사항을 받으려면 구현해야 함.
// DisplayElement - API 구조상 모든 디스플레이 항목에서 DisplayElement를 구현하기로 했기에 이 인터페이스를 구현함.
private float temperature;
private float humidity;
private WeatherData weatherData;
public CurrentConditionsDisplay(WeatherData weatherData){
//생성자에 weatherData라는 주제가 전달되며, 그 객체를 써서 디스플레이를 옵저버에 등록함.
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(){
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
//Subjcet의 게터 메소드 사용
display();
//update가 호출되면 온도와 습도를 저장하고 display()를 호출
}
public void display(){
System.out.println("현재 상태: 온도" + temperature + 'F, 습도' + humidity + "%");
//display() 메소드는 가장 최근의 온도와 습도를 출력
}
}
public class WeatherStation{
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78 , 90, 29. 2f);
}
}
public void measurementsChanged(){
float temp = getTemperature();
float humidity = getHumidity();
float pressure = getPressure();
//아래 부분들은 바뀔 수 있으므로 캡슐화 필요!
currentConditionsDisplay.update(temp, humidity, pressure);
statisticsDisplay.update(temp, humidity, pressure);
forecastDisplay.update(temp, humidity, pressure);
}
public class SwingObserverExample{
JFrame frame;
public static void main(String[] args) {
//프레임을 만들고 그 안에 버튼을 추가하는 간단한 스윙 애플리케이션
SwingObserverExample example = new SwingObserverExample();
example.go();
}
public void go(){
frame = new JFrame();
JButton button = new JButton("할까?말까?");
//람다식으로 구현
button.addActionListener(event->
System.out.println("하지마! 아마 후회할 걸?"));
button.addActionListener(event->
System.out.println("그냥 해 봐"));
}
}