ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Design Pattern] 옵저버(Observer) 패턴 - 디자인 패턴
    CSE/Design Pattern 2015. 6. 13. 10:47

    Pattern #16  옵저버 패턴



     한 객체에 의하여 영향을 받는 객체들을 정리하는데 사용






     패턴 요약 

      - 단일 객체가 영향받는 객체 집합에 대하여 같은 이름의 메소드를 호출하여 구현

      - 관찰 대상 객체가 관찰하는 객체가 몇 개인지 어떤 클래스인지 모름



     

     동기


      

      당신은 기업정보 입출력 프로그램을 개발 중이다. 이 프로그램을 이용하여 사용자들은 DB에 저장되어 있는 기업정보(월 판매액, 매출

    증가량, …)를 여러 가지 형태(도표, 꺾은선그래프, 막대그래프,..)로 볼 수 있어야 한다. 또한 관리자들이 특정 기업정보를 갱신한다면

    해당 정보를 보여주고 있는 모든 View들은 변경된 정보를 다시 반영하여 보여 주어야 한다 . 기업정보(Model) 과 보여주는

    화면(View)과의 관계를 어떻게 설계할 것인가?






     

     

     



     

     해결방안

      - Model(data)이 변경되면 이를 각 view(화면)들에게 알려줌

      - Model은 자신의 정보변경에 대한 notification을 받기를 원하는 뷰들에 대한 레퍼런스를 가지고 있어야 한다.

















    해결방안2

      - 정보변경 통보를 받은 뷰들은 모델에게서 변경된 정보를 얻어옴

      - 각 뷰들은 자신이 필요로 하는 모델에 대한 레퍼런스를 가지고 있으며, 모델에게 원하는 정보를 얻어 올 수 있다.













    해결방안3























    해결방안4

     - Model class도 향후 확장을 고려하여 class hierarchy로 구성

     - Observer pattern에서는 통지하는 역할을 Subject, 통지 받는 역할을 Observer라고 얘기함.







     









    의도

     - 한 객체의 상태가 변하면 관련된 다른 모든 객체들이 해당 상태변화를 알수 있도록 객체들 간의 one-to-many 의존관계를 정의

     




    별칭

     - Dependents, Publish-Subscribe





    적용범위

     - 시스템의 한 부분이 다른 부분에 의존적일 때, 양자를 개별적인 객체로 만들고, Observer pattern을 적용하면 독립성과 재사용성을 높일 수 있다.

     - 한 객체의 상태가 변경되면 다른 객체들도 따라 변경될 필요가 있을때 

     - 얼마나 많은 객체들이 따라서 변경되어야 하는지 알 필요가 없을 때

     - 변경을 알리는 객체와 변경을 통지 받는 객체간의 연결강도를 줄일 때





    결과

     - Subject객체와 Observer객체간의 coupling을 줄임

       * Subject객체는 단지 Observer 객체 list를 가지고 있다는 정도만 알면 된다.

       * Subject class와 Observer class가 서로 독립적으로 변경 및 확장될 수 있다.

     - Broadcast 통신에도 이용 가능

       * Observer 객체들이 원하는 subject 객체에 등록하지 않고, subject의 상태가 변화되면 전체 객체들에게 상태변화를 broadcast함

     - 예상치 못한 updates 발생가능

        * 관찰자 객체들(Observers) 간에는 상호존재를 인식하지 못하기 때문에, 한 Subject 객체의 상태변화가 전체적으로 어느 정도 만큼의 Observer 변화 비용이 드는지 알지 못함






    예제 1.




    Subject.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package observer1;
     
    public interface Subject {
        public void registerObserver(Observer o);
     
        public void removeObserver(Observer o);
     
        public void notifyAllObservers();
    }
     
     
    cs





    Observer.java

    1
    2
    3
    4
    5
    6
    7
     
    package observer1;
     
    public interface Observer {
        public void update(Subject s);
    }
     
    cs





    HeadHunter.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    package observer1;
     
    import java.util.ArrayList;
     
    public class HeadHunter implements Subject {
     
        private ArrayList<Observer> userList;
        private ArrayList<String> jobs;
     
        public HeadHunter() {
            userList = new ArrayList<Observer>();
            jobs = new ArrayList<String>();
        }
     
        public void registerObserver(Observer o) {
            userList.add(o);
        }
     
        public void removeObserver(Observer o) {
     
        }
     
        public void notifyAllObservers() {
            for (Observer o : userList) {
                o.update(this);
            }
        }
     
        public void addJob(String job) {
            this.jobs.add(job);
            notifyAllObservers();
        }
     
        public ArrayList<String> getJobs() {
            return jobs;
        }
     
        public String toString() {
            return jobs.toString();
        }
     
    }
     
    cs




    JobSeeker.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    package observer1;
     
    public class JobSeeker implements Observer {
     
        private String name;
     
        public JobSeeker(String name) {
            this.name = name;
        }
     
        public void update(Subject s) {
            System.out.println(this.name + " got notified");
     
            System.out.println(s);
        }
     
    }
     
    cs




    ObserverMain.java

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    package observer1;
     
    public class ObserverMain {
     
        public static void main(String[] args) {
            HeadHunter hh = new HeadHunter();
     
            hh.registerObserver(new JobSeeker("Kim"));
            hh.registerObserver(new JobSeeker("Lee"));
            hh.registerObserver(new JobSeeker("Park"));
     
            hh.addJob("Google Job");
            hh.addJob("Apple Job");
        }
     
    }
     
    cs

















    예제2.




    Subject.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    package observer2;
     
    public interface Observer {
        public void update();
     
        public void setSubject(Subject sub);
    }
     
    cs
     



    Observer.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    package observer2;
     
    public interface Subject {
        public void register(Observer obj);
     
        public void unregister(Observer obj);
     
        public void notifyObservers();
     
        public Object getUpdate(Observer obj);
    }
     
    cs
     



    MyTopic.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    package observer2;
     
    import java.util.ArrayList;
    import java.util.List;
     
    public class MyTopic implements Subject {
     
        private List<Observer> observers;
        private String msg;
        private boolean isChanged;
        private final Object MUTEX = new Object();
     
        public MyTopic() {
            this.observers = new ArrayList<>();
        }
     
        public void register(Observer obj) {
            if (obj == null)
                throw new NullPointerException("Null Observer");
            synchronized (MUTEX) {
                if (!observers.contains(obj))
                    observers.add(obj);
            }
        }
     
        public void unregister(Observer obj) {
            synchronized (MUTEX) {
                observers.remove(obj);
            }
        }
     
        public void notifyObservers() {
            List<Observer> observersLocal = null;
            synchronized (MUTEX) {
                if (!isChanged)
                    return;
                observersLocal = new ArrayList<>(this.observers);
                this.isChanged = false;
            }
     
            for (Observer obj : observersLocal) {
                obj.update();
            }
        }
     
        public Object getUpdate(Observer obj) {
            return this.msg;
        }
     
        public void postMessage(String msg) {
            System.out.println("Message Posted to Topic : " + msg);
            this.msg = msg;
            this.isChanged = true;
            notifyObservers();
        }
     
    }
     
    cs
     


    MyTopicSubscriber.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    package observer2;
     
    public class MyTopicSubscriber implements Observer {
     
        private String name;
        private Subject topic;
     
        public MyTopicSubscriber(String name) {
            this.name = name;
        }
     
        public void update() {
            String msg = (String) topic.getUpdate(this);
     
            if (msg == null) {
                System.out.println(name + ":: No New Message");
            } else {
                System.out.println(name + ":: Consuming message::" + msg);
            }
        }
     
        public void setSubject(Subject sub) {
            this.topic = sub;
        }
     
    }
     
    cs
     



    ObserverMain.java 

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    package observer2;
     
    public class ObserverMain {
     
        public static void main(String[] args) {
            MyTopic topic = new MyTopic();
     
            Observer obj1 = new MyTopicSubscriber("Obj1");
            Observer obj2 = new MyTopicSubscriber("Obj2");
            Observer obj3 = new MyTopicSubscriber("Obj3");
     
            topic.register(obj1);
            topic.register(obj2);
            topic.register(obj3);
     
            obj1.setSubject(topic);
            obj2.setSubject(topic);
            obj3.setSubject(topic);
     
            obj1.update();
     
            topic.postMessage("New Message");
        }
     
    }
     
    cs












    댓글

Designed by Tistory.