Observer Pattern in Design Pattern

Let's begin to learn what's Observer Pattern.

观察者模式

Overview

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。

比如,当一个对象被修改时,则会自动通知依赖它的对象。

观察者模式属于行为型模式。

主要解决

一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用

一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

应用实例

  • 拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价

优点

  • 观察者和被观察者是抽象耦合的
  • 建立一套触发机制

实现一

Observer Pattern

Observer

Observer Interface

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package individual.cy.learn.pattern.behavioral.observer.sln2;

/**
 * @author mystic
 */
public interface Observer {
    /**
     * update
     * @param event event
     */
    void update(String event);
}

People Daily

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package individual.cy.learn.pattern.behavioral.observer.sln2;

/**
 * @author mystic
 */
public class PeopleDaily implements Observer {
    @Override
    public void update(String event) {
        System.out.println("Breaking news in People Daily! event = " + event);
    }
}

New York Times

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package individual.cy.learn.pattern.behavioral.observer.sln2;

/**
 * @author mystic
 */
public class NewYorkTimes implements Observer {
    @Override
    public void update(String event) {
        System.out.println("Breaking news in New York Times! event = " + event);
    }
}

Subject

Subject Interface

 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
package individual.cy.learn.pattern.behavioral.observer.sln2;

/**
 * @author mystic
 */
public interface Subject {
    /**
     * register
     *
     * @param observer observer
     */
    void registerObserver(Observer observer);

    /**
     * unregister
     *
     * @param observer observer
     */
    void unregisterObserver(Observer observer);

    /**
     * notify all observers
     * @param event event
     */
    void notifyObservers(String event);
}

Feed

 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
package individual.cy.learn.pattern.behavioral.observer.sln2;

import java.util.ArrayList;
import java.util.List;

/**
 * @author mystic
 */
public class Feed implements Subject {
    private final List<Observer> observers = new ArrayList<>();

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

    @Override
    public void unregisterObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers(String event) {
        observers.forEach(o -> o.update(event));
    }
}

Tester

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package individual.cy.learn.pattern.behavioral.observer.sln2;

/**
 * @author mystic
 */
public class Tester {
    public static void main(String[] args) {
        Feed globalEvent = new Feed();

        Observer newYorkTimes = new NewYorkTimes();
        Observer peopleDaily = new PeopleDaily();

        globalEvent.registerObserver(newYorkTimes);
        globalEvent.registerObserver(peopleDaily);

        globalEvent.notifyObservers("Violent Parade in USA");

        System.out.println("Unregister New York Times!");
        globalEvent.unregisterObserver(newYorkTimes);
        globalEvent.notifyObservers("Violent Parade in Canada");
    }
}

1
2
3
4
Breaking news in New York Times! event = Violent Parade in USA
Breaking news in People Daily! event = Violent Parade in USA
Unregister New York Times!
Breaking news in People Daily! event = Violent Parade in Canada

实现二

Observer Pattern

Observer

Abstract Observer

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package individual.cy.learn.pattern.behavioral.observer;

/**
 * @author mystic
 */
public abstract class AbstractObserver {
    protected Subject subject;

    /**
     * update
     */
    public abstract void update();
}

Binary Observer

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package individual.cy.learn.pattern.behavioral.observer;

/**
 * @author mystic
 */
public class BinaryObserver extends AbstractObserver {
    public BinaryObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        System.out.println("BinaryObserver.update: " + Integer.toBinaryString(subject.getState()));
    }
}

Octal Observer

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package individual.cy.learn.pattern.behavioral.observer;

/**
 * @author mystic
 */
public class OctalObserver extends AbstractObserver {

    public OctalObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        System.out.println("OctalObserver.update: " + Integer.toOctalString(subject.getState()));
    }
}

Hex Observer

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package individual.cy.learn.pattern.behavioral.observer;

/**
 * @author mystic
 */
public class HexObserver extends AbstractObserver {
    public HexObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        System.out.println("HexObserver.update: " + Integer.toHexString(subject.getState()).toUpperCase());
    }
}

Subject

 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
package individual.cy.learn.pattern.behavioral.observer;

import java.util.ArrayList;
import java.util.List;

/**
 * @author mystic
 */
public class Subject {
    private final List<AbstractObserver> observerList = new ArrayList<>();

    private int state;

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
        notifyAllObservers();
    }

    public void attach(AbstractObserver observer) {
        observerList.add(observer);
    }

    public void notifyAllObservers() {
        observerList.forEach(AbstractObserver::update);
    }
}

Tester

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package individual.cy.learn.pattern.behavioral.observer;

/**
 * @author mystic
 */
public class ObserverPatternTester {
    public static void main(String[] args) {
        Subject subject = new Subject();
        new HexObserver(subject);
        new OctalObserver(subject);
        new BinaryObserver(subject);

        System.out.println("First state change: 15");
        subject.setState(15);
        System.out.println("========================");
        System.out.println("Second state change: 10");
        subject.setState(10);
    }
}

1
2
3
4
5
6
7
8
9
First state change: 15
HexObserver.update: F
OctalObserver.update: 17
BinaryObserver.update: 1111
========================
Second state change: 10
HexObserver.update: A
OctalObserver.update: 12
BinaryObserver.update: 1010