[디자인 패턴] 옵저버 패턴 (Observer Pattern)

최진민·2021년 11월 16일
0

디자인 패턴

목록 보기
7/10
post-thumbnail
  • 정의
  • 구현


🎧 1. 옵저버 패턴 ?

  • 옵저버 패턴 (Observer Pattern)

    • 특정 객체에 상태가 변할 때(=이벤트가 발생할 때), 그와 연관된 객체들에게 알려주고 자동으로 갱신이 되도록 하는 전형적인 One-to-Many(1:N)의 디자인 패턴

    • Publish/Subscribe 모델이라고 불리기도 함.

    • 가장 전형적인 예 - Youtube

      • Youtuber (유튜버) = Subject (주체) = Publisher
      • Subcriber (구독자) = Observer (관찰자)
    • 구조



🎻 2. 구현

  • 과거에는 사용자(Observer)신문사(Subject)정기 구독을 요청하면, 신문사는 옵저버의 정보(주소 등)를 업데이트한 후, 신청한 사용자 모두에게 매일 아침 새로운 내용의 신문을 배달했다. 또한, 배달을 원치 않을 때, 사용자는 구독을 해제할 수도 있다.

  • Publisher => 신문사

    public interface Publisher {
        void add(Observer observer);
        void delete(Observer observer);
        void notifyObserver();
    }
    • 구독자를 추가(add), 삭제(delete)하거나 구독자에게 알려주는 기능(notifyObserver)를 추가
    import java.util.ArrayList;
    import java.util.List;
    
    public class NewsCompany implements Publisher {
        private List<Observer> observers;
        private String newsTitle;
    
        public NewsCompany(){
            observers = new ArrayList<>();
        }
    
        @Override
        public void add(Observer observer) {
            observers.add(observer);
        }
    
        @Override
        public void delete(Observer observer) {
            int idx = observers.indexOf(observer);
            observers.remove(idx);
        }
    
        @Override
        public void notifyObserver() {
            for (Observer observer : observers) {
                observer.update(newsTitle);
            }
        }
    
        public void setNewsTitle(String newsTitle){
            this.newsTitle = newsTitle;
            notifyObserver();
        }
    }
    • List<Observer> observers를 통해 1:N연관관계가 성립하고, 변경할 데이터(newsTitle)에 대한 변수를 선언하여 메서드(setNewsTitle())를 통해 변경하도록 구현
  • Observer => 신문 구독자들

    public interface Observer {
        void update(String contents);
    }
    • 변경된 내용을 업데이트하는 메서드 update()가 있다.
    public class First implements Observer {
        private Publisher publisher;
        private String contents;
    
        public First(Publisher publisher) {
            this.publisher = publisher;
            publisher.add(this);
        }
    
        @Override
        public void update(String contents) {
            this.contents = contents;
            System.out.println("변경된 신문사의 내용 (First) : " + this.contents);
        }
    }
    
    ////
    public class Second implements Observer {
        private Publisher publisher;
        private String contents;
    
        public Second(Publisher publisher) {
            this.publisher = publisher;
            publisher.add(this);
        }
    
        @Override
        public void update(String contents) {
            this.contents = contents;
            System.out.println("변경된 신문사의 내용 (Second) : " + this.contents);
        }
    }
    • First, Second 두 명의 구독자가 존재
    public class Main {
        public static void main(String[] args) {
            NewsCompany newsCompany = new NewsCompany();
    
            First first = new First(newsCompany);
            Second second = new Second(newsCompany);
    
            newsCompany.setNewsTitle("초 대박 뉴스!!!!");
            System.out.println("-----------");
            newsCompany.setNewsTitle("초초초 대박 뉴스!!!!");
        }
    }
    
    print: >>>
    변경된 신문사의 내용 (First) : 초 대박 뉴스!!!!
    변경된 신문사의 내용 (Second) : 초 대박 뉴스!!!!
    -----------
    변경된 신문사의 내용 (Frist) : 초초초 대박 뉴스!!!!
    변경된 신문사의 내용 (Second) : 초초초 대박 뉴스!!!!
    • 한 개의 신문사를 설립(NewsCompany newsCompany = new NewsCompany();)

    • 각 구독자들은 생성시점에 신문사에 구독

    • 데이터가 변경될 때마다 알림

    • 구독을 해제하는 경우에, 해제의 주체는 신문사가 아닌 구독자이다.

      public class First implements Observer {
          //...
          public void unsubscribe() {
              publisher.delete(this);
          }
      }
      public class Main {
          public static void main(String[] args) {
              NewsCompany newsCompany = new NewsCompany();
      
              First first = new First(newsCompany);
              Second second = new Second(newsCompany);
      
              newsCompany.setNewsTitle("초 대박 뉴스!!!!");
              System.out.println("-----------");
              newsCompany.setNewsTitle("초초초 대박 뉴스!!!!");
      
              first.unsubscribe();
      
              System.out.println("First 구독 취소 후,,,,,,,");
              newsCompany.setNewsTitle("나쁜 내용의 뉴스");
          }
      }
      
      print >>>
      변경된 신문사의 내용 (First) : 초 대박 뉴스!!!!
      변경된 신문사의 내용 (Second) : 초 대박 뉴스!!!!
      -----------
      변경된 신문사의 내용 (First) : 초초초 대박 뉴스!!!!
      변경된 신문사의 내용 (Second) : 초초초 대박 뉴스!!!!
      First 구독 취소 후,,,,,,,
      변경된 신문사의 내용 (Second) : 나쁜 내용의 뉴스
  • 결론

    • 주제자(Subject)는 옵저버(Observer)가 무슨 동작을 하는지 모른다. 옵저버가 추가되거나 제거되어도 주제에 전혀 영향을 주지 않는다. = 느슨한 결합
profile
열심히 해보자9999

0개의 댓글