πŸ“– [λ””μžμΈνŒ¨ν„΄] πŸ’» Observer Pattern (μ˜΅μ €λ²„ νŒ¨ν„΄/κ΄€μ°°μž νŒ¨ν„΄)

πŸ’» Observer Pattern (μ˜΅μ €λ²„ νŒ¨ν„΄/κ΄€μ°°μž νŒ¨ν„΄)

μ•ˆλ…•ν•˜μ„Έμš”. πŸ‘‹

μ˜€λŠ˜μ€ Observer Pattern (κ΄€μ°°μž νŒ¨ν„΄ ) 에 λŒ€ν•΄

μ•Œμ•„λ³΄λ €κ³  ν•©λ‹ˆλ‹€.

What is Observer Pattern? (μ˜΅μ €λ²„ νŒ¨ν„΄μ΄λž€?)

  • Observer Pattern μ΄λž€

    μ˜΅μ„œλ²„ νŒ¨ν„΄(observer pattern)은 객체의 μƒνƒœ λ³€ν™”λ₯Ό κ΄€μ°°ν•˜λŠ” κ΄€μ°°μžλ“€, 즉 μ˜΅μ €λ²„λ“€μ˜ λͺ©λ‘μ„ 객체에 λ“±λ‘ν•˜μ—¬ μƒνƒœ λ³€ν™”κ°€ μžˆμ„ λ•Œλ§ˆλ‹€
    λ©”μ„œλ“œ 등을 톡해 객체가 직접 λͺ©λ‘μ˜ 각 μ˜΅μ €λ²„μ—κ²Œ ν†΅μ§€ν•˜λ„λ‘ ν•˜λŠ” λ””μžμΈ νŒ¨ν„΄μ΄λ‹€. 주둜 λΆ„μ‚° 이벀트 핸듀링 μ‹œμŠ€ν…œμ„ κ΅¬ν˜„ν•˜λŠ” 데 μ‚¬μš©λœλ‹€.
    λ°œν–‰/ꡬ독 λͺ¨λΈλ‘œ μ•Œλ €μ Έ μžˆκΈ°λ„ ν•˜λ‹€.
    
    좜처(μœ„ν‚€λ°±κ³Ό) https://ko.wikipedia.org/wiki/%EC%98%B5%EC%84%9C%EB%B2%84_%ED%8C%A8%ED%84%B4
    

Observer Pattern의 ν™œμš©

μ˜΅μ €λ²„ νŒ¨ν„΄μ˜ μ •μ˜μ²˜λŸΌ 보톡 λ°œν–‰/ꡬ독 λͺ¨λΈλ‘œ μ•Œλ €μ ΈμžˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ κ΄€μ°°μžνŒ¨ν„΄μ΄λΌκ³ λ„ ν•©λ‹ˆλ‹€. ν•˜λ‚˜μ˜ Publisher(λ°œν–‰μž)μ—κ²Œ μ—¬λŸ¬ Subscriber (κ΅¬λ…μž)κ°€ μžˆμ„ 수 있기 λ•Œλ¬Έμ— μΌλŒ€μΌμ΄λ‚˜ μΌλŒ€λ‹€ 관계λ₯Ό 이룰수 μžˆμŠ΅λ‹ˆλ‹€. 그리고 Publisher(λ°œν–‰μž)의 μƒνƒœκ°€ μ—…λ°μ΄νŠΈλœλ‹€λ©΄ 이 Publisher(λ°œν–‰μž)λ₯Ό ꡬ독(κ΄€μ°°)ν•˜κ³  μžˆλŠ” μ˜΅μ €λ²„λ“€μ—κ²Œ μ—…λ°μ΄νŠΈκ°€ λ˜μ—ˆμŒμ„ μ•Œλ €μ€λ‹ˆλ‹€.

μ˜΅μ €λ²„ νŒ¨ν„΄μ€ ν‘Έμ‹œ 방식과 ν’€ 방식이 μžˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ Publisher의 μ •λ³΄λ‚˜ μƒνƒœκ°€ 변경될 λ•Œλ§ˆλ‹€ Observerμ—κ²Œ μ „νŒŒν•΄μ£ΌλŠ” 것이 Push방식이고 Observerμ—μ„œ 정보가 ν•„μš”ν•  λ•Œλ§ˆλ‹€ Publisherμ—κ²Œ κ°€μ Έμ˜€λŠ” 방식을 Pull방식이라고 ν•©λ‹ˆλ‹€.

이 μ˜΅μ €λ²„ νŒ¨ν„΄μ˜ λŒ€ν‘œμ μΈ μ‚¬μš©μ²˜λŠ” μžλ°”μ˜ Swingμ΄λ‚˜ μ•ˆλ“œλ‘œμ΄λ“œμ˜ Viewλ‚˜ Button λ“±μ˜ μœ„μ ―μ—μ„œ 각쒅 이벀트λ₯Ό 받을 λ•Œ μ“°μž…λ‹ˆλ‹€.


Observer Pattern 적용 μ˜ˆμ‹œ

μ˜΅μ €λ²„ νŒ¨ν„΄μ„ μ’€ 더 μ΄ν•΄ν•˜κΈ° μ‰½κ²Œ ν•˜κΈ°μœ„ν•΄ λ‰΄μŠ€ κ΅¬λ…μ΄λ‚˜ 유튜브 ꡬ독등을 μ˜ˆμ‹œλ‘œ λ“€μˆ˜μžˆμŠ΅λ‹ˆλ‹€. 유튜브 ꡬ독을 μ˜ˆμ‹œλ‘œ λ³΄μ—¬λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€.

보톡 ν”νžˆ λ§Žμ΄λ“€ ν•˜λŠ” κ²ƒμ²˜λŸΌ μ–΄λ–€ 유튜브 채널을 κ΅¬λ…ν•˜κ³  μ•Œλ¦Όμ„ 섀정해두면 κ΅¬λ…ν•œ 채널(Publihser)의 μ˜μƒμ΄ μƒˆλ‘œ 올라올 λ•Œ (Publisher 정보 μ—…λ°μ΄νŠΈ) κ΅¬λ…ν•œ μ‚¬λžŒλ“€μ—κ²Œ(Subscriber / Observer) μ•Œλ €μ€λ‹ˆλ‹€. (push 방식)

λ˜ν•œ κ΅¬λ…ν•΄μ œλ₯Ό 톡해 ꡬ독을 κ·Έλ§Œλ‘˜ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. (unsubscribe)

diagram

Publisher μΈν„°νŽ˜μ΄μŠ€

package observer;

public interface Publisher {
    public void add(Observer observer);

    public void delete(Observer observer);

    public void notifyObserver();

}

Observer μΈν„°νŽ˜μ΄μŠ€

package observer;

public interface Observer {
    public void update(String title, String content);
}

YoutubeChannel 클래슀 (Publisher)

package observer;
import java.util.ArrayList;
import java.util.List;

public class YoutubeChannel implements Publisher{
    private List<Observer> observerList;
    private String title;
    private String content;

    public YoutubeChannel() {
        this.observerList = new ArrayList<>();
    }

    @Override
    public void add(Observer observer) {
        observerList.add(observer);
    }

    @Override
    public void delete(Observer observer) {
        int targetIndex = observerList.indexOf(observer);
        observerList.remove(targetIndex);
    }

    @Override
    public void notifyObserver() {
        for(Observer observer : observerList) {
            observer.update(title, content);
        }
    }

    public List<Observer> getObserverList() {
        return observerList;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setNewsInfo(String title, String content) {
        this.title = title;
        this.content = content;
        notifyObserver();
    }
}

AnnualSubscriber 클래슀 (Subscriber / Observer)

package observer;

public class AnnualSubscriber implements Observer {
    private String newsString;
    private Publisher publisher;

    public AnnualSubscriber(Publisher publisher) {
        this.publisher = publisher;
        publisher.add(this);
    }

    @Override
    public void update(String title, String content) {
        this.newsString = "title : " + title + "\n" + "content : " + content + "\n========";
        display();
    }

    public void unsubscribe() {
        this.publisher.delete(this);
    }

    private void display() {
        System.out.println("AnnualSubscriber \n");
        System.out.println("Today News\n" + newsString);
    }
}

EventSubscriber 클래슀 (Subscriber / Observer)

package observer;

public class EventSubscriber implements Observer {
    private String newsString;
    private Publisher publisher;

    public EventSubscriber(Publisher publisher) {
        this.publisher = publisher;
        publisher.add(this);
    }

    @Override
    public void update(String title, String content) {
        this.newsString = "title : " + title + "\n" + "content : " + content + "\n========";
        display();
    }

    public void unsubscribe() {
        this.publisher.delete(this);
    }

    private void display() {
        System.out.println("EventSubscriber \n");
        System.out.println("Today News\n" + newsString);
    }
}

Main문

package observer;

public class Main {
    public static void main(String[] args) {
        YoutubeChannel youtubeChannel = new YoutubeChannel();
        AnnualSubscriber annualSubscriber = new AnnualSubscriber(youtubeChannel);
        EventSubscriber eventSubscriber = new EventSubscriber(youtubeChannel);
        youtubeChannel.setNewsInfo("첫 μ˜μƒμž…λ‹ˆλ‹€.", "μ•ˆλ…•ν•˜μ„Έμš”!");
        youtubeChannel.setNewsInfo("λ‘λ²ˆμ§Έ μ˜μƒμž…λ‹ˆλ‹€.", "또 λ΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€!");

        eventSubscriber.unsubscribe();
        System.out.println("eventSubscriber νƒˆν‡΄ ν›„\n\n");
        youtubeChannel.setNewsInfo("κ΅¬λ…μžκ°€ 100만λͺ…이 λ˜μ—ˆμŠ΅λ‹ˆλ‹€", "κ°μ‚¬ν•©λ‹ˆλ‹€!");
    }
}

μ‹€ν–‰κ²°κ³Ό

result


끝

μ˜€λŠ˜μ€ μ˜΅μ €λ²„(κ΄€μ°°μž) νŒ¨ν„΄ (observer pattern)에 λŒ€ν•΄ μ•Œμ•„λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

κ°μ‚¬ν•©λ‹ˆλ‹€. πŸ™

Reference

https://ko.wikipedia.org/wiki/%EC%98%B5%EC%84%9C%EB%B2%84_%ED%8C%A8%ED%84%B4

https://flowarc.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%98%B5%EC%A0%80%EB%B2%84-%ED%8C%A8%ED%84%B4Observer-Pattern

Written on January 20, 2021