DevLog ๐Ÿ˜ถ

[ReactiveProgramming] Iterable, Iterator์™€ Observer Pattern ๋ณธ๋ฌธ

Back-end/Spring

[ReactiveProgramming] Iterable, Iterator์™€ Observer Pattern

dolmeng2 2022. 10. 24. 13:45

 

- ํ† ๋น„์˜ '์Šคํ”„๋ง ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ' ๊ฐ•์˜๋ฅผ ๋“ฃ๊ณ  ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

 

 

- ์ „์ฒด ์†Œ์Šค์ฝ”๋“œ) https://github.com/Cl8D/SpringReactive

 

GitHub - Cl8D/SpringReactive: Spring Reactive Programming ํ•™์Šต ์šฉ๋„ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ์ž…๋‹ˆ๋‹ค.

Spring Reactive Programming ํ•™์Šต ์šฉ๋„ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ์ž…๋‹ˆ๋‹ค. Contribute to Cl8D/SpringReactive development by creating an account on GitHub.

github.com


โœ”๏ธ Iterable / Iterator

package chapter1;

        import java.util.Iterator;

public class Basic {
    public static void main(String[] args) {
        // Iterable์„ ๊ตฌํ˜„ํ•œ ๊ตฌํ˜„์ฒด ์ƒ์„ฑ
        Iterable<Integer> iter = () ->
        // Iterator๋ผ๋Š” ๋„๊ตฌ๋ฅผ custom ํ•˜๊ธฐ
        new Iterator<Integer>() {
            // 1~10๊นŒ์ง€ ์ƒ์„ฑ
            int i = 0;
            final static int MAX = 10;

            @Override
            public boolean hasNext() {
                return i < MAX;
            }

            @Override
            public Integer next() {
                return ++i; // ๋‹ค์Œ ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ
            }
        };

        // custom์ด์ง€๋งŒ for-each ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ. (enhanced for)
        // ์ฆ‰, ์ž๋ฐ”์—์„œ for-each๋Š” Iterable์˜ ๊ตฌํ˜„์ฒด์—์„œ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
        for(Integer i : iter) {
            System.out.println(i);
        }

        // Java 10 ๋ฒ„์ „
        for(Iterator<Integer> it = iter.iterator(); it.hasNext();) {
            // pull์˜ ๋Š๋‚Œ, ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ.
            System.out.println(it.next());
        }
    }
}
  • 1~10๊นŒ์ง€ ์ƒ์„ฑํ•˜๋Š” Iterator ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ธฐ.
  • ์ด๋•Œ hatNext()์™€ next()๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•ด์„œ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • hasNext()๋Š” ๋‹ค์Œ ์š”์†Œ๊ฐ€ ์žˆ๋Š”์ง€, next()๋Š” ๋‹ค์Œ ์š”์†Œ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ.
  • for-each ๊ตฌ๋ฌธ์€ ์ด๋ ‡๊ฒŒ ์ปค์Šคํ…€ํ•œ ๊ฐ์ฒด์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์ฆ‰, Iterable์˜ ๊ตฌํ˜„์ฒด๋ผ๋ฉด enhanced for๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

โœ”๏ธ Observer

  • Full Code
package chapter1;

        import java.util.Observable;
        import java.util.Observer;
        import java.util.concurrent.ExecutorService;
        import java.util.concurrent.Executors;

@SuppressWarnings("deprecation")
public class ObserverTest {

    /**
     * 1. ์˜ต์ €๋ฒ„ ํŒจํ„ด์—๊ฒŒ๋Š” complete๊ฐ€ ์—†๋‹ค.
     * 2. ์ฝ”๋“œ๊ฐ€ ๋™์ž‘ํ•˜๋‹ค ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ์˜ˆ์™ธ ์ „ํŒŒ ๋ฐฉ์‹, ์—์™ธ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์— ๋Œ€ํ•ด ์–ด๋ ค์›Œ์ง„๋‹ค.
     */

    public static void main(String[] args) {
        // iterable ๋•Œ๋ฌธ์— deprecate๋œ ์นœ๊ตฌ...
        Observer observer1 = new Observer() {
            // ์ผ์ข…์˜ subscriber
            // notifyObservers ๋™์ž‘ ์‹œ ์‹คํ–‰๋œ๋‹ค.
            // ์ฆ‰, observable์ด ๋˜์ง„ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์„œ ์ถœ๋ ฅํ•ด์ฃผ๋Š” ์—ญํ• !
            @Override
            public void update(Observable o, Object arg) {
                System.out.println("observer1 = " + arg);
            }
        };

        Observer observer2 = new Observer() {
            @Override
            public void update(Observable o, Object arg) {
                System.out.println("observer2 = " + arg);
            }
        };

        Observer observer3 = new Observer() {
            @Override
            public void update(Observable o, Object arg) {
                System.out.println("observer3 = " + arg);
            }
        };

        IntObservable io = new IntObservable();
        // observer๋ฅผ ๋“ฑ๋กํ•ด์ค€๋‹ค. ์ด๋Ÿฌ๋ฉด observable์ด ๋˜์ง„ ์ž‘์—…์„ ๋“ฑ๋ก๋œ ์˜ต์ €๋ฒ„๋“ค์ด ๋ฐ›๋Š”๋‹ค.
        // ์‹คํ–‰ ์ˆœ์„œ์˜ ๊ฒฝ์šฐ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ๋“ฑ๋กํ•ด์ค€ ์˜ต์ €๋ฒ„๋ถ€ํ„ฐ ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.
        io.addObserver(observer1);
        io.addObserver(observer2);
        io.addObserver(observer3);

        // Executors๋ฅผ ํ†ตํ•ด์„œ ExecutorService ์ƒ์„ฑ ๊ฐ€๋Šฅ
        // ์Šค๋ ˆ๋“œ๋ฅผ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑํ•ด์ค€ ๋‹ค์Œ์— ํ• ๋‹นํ•ด์ฃผ๊ธฐ
        ExecutorService es = Executors.newSingleThreadExecutor();
        es.execute(io);

        // execute๋ณด๋‹ค ๋‚˜์ค‘์— ์ž…๋ ฅํ–ˆ๋Š”๋ฐ๋„ ๋” ๋จผ์ € ์‹คํ–‰๋œ๋‹ค.
        // excute๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑํ•ด์„œ (๋ณ„๊ฐœ์˜ ์Šค๋ ˆ๋“œ) ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋‚˜์ค‘์— ๋™์ž‘ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ
        System.out.println("Hello!");
        es.shutdown();
    }

    // observable์€ ์™ธ๋ถ€์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋‚ด์•ผ ํ•œ๋‹ค.
    // ๋น„๋™๊ธฐ๋กœ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ runnable ๊ตฌํ˜„
    static class IntObservable extends Observable implements Runnable {
        @Override
        public void run() {
            for(int i=1; i<=10; i++) {
                setChanged(); // ๋ณ€ํ™”๊ฐ€ ์ƒ๊ฒผ์Œ์„ ์•Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•ด์„œ, Observable์— ๋“ฑ๋ก๋˜์–ด ์žˆ์Œ.
                // ์ผ์ข…์˜ Push ๋Š๋‚Œ. ์‚ฌ์‹ค iter์—์„œ์˜ it.next()์™€ ๋น„์Šทํ•œ ๋Š๋‚Œ์ด๋‹ค.
                notifyObservers(i); // ์˜ต์ €๋ฒ„์—๊ฒŒ ์•Œ๋ ค์ฃผ๊ธฐ!, ์ผ์ข…์˜ publisher
            }
        }
    }
}
  • ์˜ต์ €๋ฒ„ ํŒจํ„ด
    • complete()๊ฐ€ ์—†๋‹ค.
    • ์ฝ”๋“œ๊ฐ€ ๋™์ž‘ํ•˜๋‹ค ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ์ „ํŒŒ๋˜๋ฉฐ, ์ด ๊ฒฝ์šฐ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•ด ๊นŒ๋‹ค๋กœ์›Œ์ง„๋‹ค.
  • Observer ๊ฐ์ฒด
    • ์ผ์ข…์˜ subscriber๋กœ์„œ, notifyObservers๊ฐ€ ๋™์ž‘ํ•˜๋ฉด ์‹คํ–‰๋œ๋‹ค.
    • ์ฆ‰, observable์ด ๋˜์ง„ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์„œ ์ถœ๋ ฅํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
  Observer observer1 = new Observer() {
@Override
public void update(Observable o, Object arg) {
        System.out.println("observer1 = " + arg);
        }
        };

        Observer observer2 = new Observer() {
@Override
public void update(Observable o, Object arg) {
        System.out.println("observer2 = " + arg);
        }
        };

        Observer observer3 = new Observer() {
@Override
public void update(Observable o, Object arg) {
        System.out.println("observer3 = " + arg);
        }
        };
  • IntObservable
    • IntObservable์— ์˜ต์ €๋ฒ„๋ฅผ ๋“ฑ๋กํ•ด์ฃผ๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ, observable์ด ๋˜์ง„ ์ž‘์—…์„ ๋“ฑ๋ก๋œ ์˜ต์ €๋ฒ„๋“ค์ด ๋ฐ›๊ฒŒ ๋œ๋‹ค.
    • ์‹คํ–‰์€ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์œผ๋กœ ๋“ฑ๋กํ•œ ์˜ต์ €๋ฒ„๋ถ€ํ„ฐ ์—ญ์œผ๋กœ ์ˆ˜ํ–‰๋œ๋‹ค.
    • observer3 = 1
    • observer2 = 1
    • observer1 = 1
    • observer3 = 2
    • observer2 = 2
    • observer1 = 2 ...
        IntObservable io = new IntObservable();
        io.addObserver(observer1);
        io.addObserver(observer2);
        io.addObserver(observer3);
  • ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜๋„๋ก ์ƒ์„ฑ
    • main ์Šค๋ ˆ๋“œ๊ฐ€ ์•„๋‹Œ ๋ณ„๊ฐœ์˜ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰ํ•˜์˜€๊ธฐ ๋•Œ๋ฌธ์— Hello! ์‹คํ–‰ ๋’ค์— ์ˆœ์ฐจ์ ์œผ๋กœ ๊ฒฐ๊ณผ๊ฐ’์ด ์ถœ๋ ฅ๋œ๋‹ค.
      ExecutorService es = Executors.newSingleThreadExecutor();
        es.execute(io);

        System.out.println("Hello!");
        es.shutdown();
  • ์™ธ๋ถ€์—์„œ ์ด๋ฒคํŠธ ์ƒ์„ฑํ•ด์ฃผ๊ธฐ
    • Runnable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋Š” ๋น„๋™๊ธฐ๋กœ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค.
    • Observable์˜ setchanged() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด Observable ๊ฐ์ฒด์— ๋ณ€ํ™”๊ฐ€ ์ƒ๊ฒผ์Œ์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ ๋‚ด๋ถ€์ ์œผ๋กœ changed ๋ณ€์ˆ˜๊ฐ€ true๋กœ ์„ธํŒ…๋œ๋‹ค.
    • notifyObservers() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ผ์ข…์˜ publisher๋กœ์„œ, ๋“ฑ๋ก๋œ Observer๋“ค์—๊ฒŒ ๋ณ€ํ™”๋œ ๋‚ด์šฉ์„ ์—…๋ฐ์ดํŠธํ•ด์ค€๋‹ค.
static class IntObservable extends Observable implements Runnable {
    @Override
    public void run() {
        for(int i=1; i<=10; i++) {
            setChanged(); // ๋ณ€ํ™”๊ฐ€ ์ƒ๊ฒผ์Œ์„ ์•Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•ด์„œ, Observable์— ๋“ฑ๋ก๋˜์–ด ์žˆ์Œ.
            // ์ผ์ข…์˜ Push ๋Š๋‚Œ. ์‚ฌ์‹ค iter์—์„œ์˜ it.next()์™€ ๋น„์Šทํ•œ ๋Š๋‚Œ์ด๋‹ค.
            notifyObservers(i); // ์˜ต์ €๋ฒ„์—๊ฒŒ ์•Œ๋ ค์ฃผ๊ธฐ!, ์ผ์ข…์˜ publisher
        }
    }
}
Comments