javascript에서 Observer 패턴

요즈음의 프런트 엔드 기술은 진보가 압도적으로 빠르고,
jQuery 알아요! MV * 프레임 워크 사용한 적이 있습니다!
라고 하는 정도로는 더 이상 기술에 대해 안 되어 버리고 있는 요즘입니다.

기술을 따라갈 수 있을 만큼의 기초 체력을 붙이기 위해서, GUI 프로그램에 있어서의 MVC 패턴의 디자인 패턴에 대해 학습한 것을 써 갑니다.

우선 Observer 패턴에서 ...
라고 생각해 GUI에 있어서의 MVC를 여러가지 조사하고 있었습니다만, 필수인 것은 Observer 패턴(과 그 파생)뿐이었다고 하는 결론에 이르렀으므로 더 이상 javascript의 디자인 패턴에 대해서는 투고하는 것을 그만두었습니다.

MVC에 대해서는, 하기 투고나,
smalltalk의 MVC에 대해 보면 괜찮다고 생각합니다.

MVC, 정말 알고 계십니까?
smalltalk mvc

게시자 배경



참고까지 쓴다.
  • 웹 애플리케이션 서버 측 프로그램 메인 개발
  • 프런트 엔드는 MV * 프레임 워크 등 이용 가능하지만, 개념까지는 설명 할 수없는 느슨한 푹신한 시스템
  • GUI 프로그램은 객체 지향이없는 언어로 경험이 있습니다

  • Observer 패턴이란?



    이벤트에 의해 상태를 갱신하는 Observer와, 그 Observer의 등록이나 삭제, 이벤트의 통지를 하는 Subject로 구성된다.

    Subject는 등록된 Observer에 통지를 하는 것만으로 좋고,
    Observer가 무엇인지에 관심이 없어도 좋다.

    라고 어려워 썼지만, 요점은 Subject와 Observer로 나누는 것으로 이벤트의 대상과 이벤트의 발행이 느슨하게 결합할 수 있는 디자인 패턴.

    그 밖에, Observer의 상태에 일관성을 갖게 할 수 있다고 하는 효용도 있는 것 같습니다.

    샘플 프로그램으로 살펴보기



    버튼을 클릭하면 박스의 칼라가 바뀐다고 하는 프로그램을 상정.
    버튼 1을 클릭하면 빨간색으로,
    버튼 2를 클릭하면 파란색으로,
    버튼 3을 클릭하면 빨간색으로 바뀌고 파란색으로 바뀝니다.

    Observer 패턴을 사용하지 않는 프로그램


    btn1 = document.getElementById 'btn1'
    btn2 = document.getElementById 'btn2'
    btn3 = document.getElementById 'btn3'
    
    box1 = document.getElementById 'box1' 
    box2 = document.getElementById 'box2'
    
    btn1.onclick = () ->
      to_red = 'red'
    
      box1.style.backgroundColor = to_red
      box2.style.backgroundColor = to_red
    
    btn2.onclick = () ->
      to_blue = 'blue'
    
      box1.style.backgroundColor = to_blue
      box2.style.backgroundColor = to_blue
    
    btn3.onclick = () ->
      to_red = 'red'
      to_blue = 'blue'
    
      box1.style.backgroundColor = to_red
      box2.style.backgroundColor = to_red
    
      setTimeout () ->
        box1.style.backgroundColor = to_blue
        box2.style.backgroundColor = to_blue
      , 500
    

    각 클릭 이벤트에서는 이벤트의 대상이 되는 객체를 모르면 처리를 쓸 수 없다는 것을 알 수 있습니다.

    Observer 패턴 적용



    Subject 및 Observer 객체 정의


    class Subject
      _observers = []
    
      add: (observer) ->
        _observers.push(observer)
    
      notify: (context) ->
        for observer in _observers
          observer.update(context)
    
    class Observer
      update: (context) ->
    
  • Subject

  • Observer의 등록과, 등록한 Observer에 이벤트의 통지를 실시한다.
    (실제는 Subject 객체에는 등록한 Observer를 삭제하는 메소드도 필요합니다만, 이번 샘플에서는 이용하지 않으므로 생략하고 있습니다.)
  • Observer

  • 자신의 상태를 갱신하는 메소드를 가집니다.

    상속을 위한 함수 준비



    위에서 정의한 Subject와 Object도 추상 객체로 사용합니다.
    따라서 상속을 위한 함수를 정의합니다.
    extend = (obj, extension) ->
      for key, prop of obj
        extension[key] = obj[key]
    

    실제 처리


    btn1 = document.getElementById 'btn1'
    btn2 = document.getElementById 'btn2'
    btn3 = document.getElementById 'btn3'
    
    for btn in [btn1, btn2, btn3]
      extend new Subject(), btn
    
    box1 = document.getElementById 'box1' 
    box2 = document.getElementById 'box2'
    
    for box in [box1, box2]
      extend new Observer(), box
    
      box.update = (color) ->
        box.style.backgroundColor = color
    
      for btn in [btn1, btn2, btn3]
        btn.add box
    
    btn1.onclick = () ->
      this.notify 'red'
    
    btn2.onclick = () ->
      this.notify 'blue'
    
    btn3.onclick = () ->
      self = this
    
      self.notify 'red'
    
      setTimeout () ->
        self.notify 'blue'
      , 500
    

    각 클릭 이벤트는 대상을 알 필요가 없으며,
    상태 알림만 하면 됩니다.

    이벤트의 대상과 발행을 깨끗하게 분리할 수 있었습니다

    Observer 패턴 파생



    출판 - 구독형 모델
    이벤트 중심 프로그래밍

    좋은 웹페이지 즐겨찾기