设计模式-观察者模式 实现

观察者模式:

  已一对多的方式,通过制定一个主题,使多个不同的订阅者能时时的接收到最新的消息。

   注意.观察者模式的通知次序是不被依赖的,若你需要明确通知次序或者对通知的顺序有强烈的要求那么请酌情使用该模式。

定义一个主题:

主题中处理基本的添加/删除 订阅者  消息发布 还加入一个change锁  可以负责消息发布的控制,将灵活的控制消息的发布,减少不必要的消息传播。

消息的发布主要是依靠接口的特性传播,通过实现一个订阅者接口来设定订阅者,主题不需要具体的订阅者是谁,只需要在消息更新时对这个接口的所有实现发布即可。

public interface Subjects {

    void add(Object obj);

    void remove(Object obj);

    void notifyObserver();

    void setMessage(String msg);

    void setChange();

}
View Code
public class Subject implements Subjects{
    
    private ArrayList<Object> observers;
    
    private String message;
    
    private boolean lock;
    
    public Subject() {
        observers = new ArrayList<>();
    }
    
    @Override
    public void add(Object obj) {
        observers.add(obj);
    }
    
    @Override
    public void remove(Object obj) {
        int i = observers.indexOf(obj);
        if (i > 0) {
            observers.remove(obj);
        }
    }
    
    @Override
    public void notifyObserver() {
        if (lock) {
            for (int i = 0; i < observers.size(); i++) {
                Observers observer = (Observers)observers.get(i);
                observer.update(message);
            }
            lock = false;
        }
    }
    
    public void change() {
        setChange();
        notifyObserver();
    }
    
    @Override
    public void setMessage(String msg) {
        this.message = msg;
        change();
    }
    
    @Override
    public void setChange() {
        lock = true;
    }
}
View Code

订阅者

 主题消息的发布与订阅者之间有个共同的方法,通过这个方法订阅者来接受发布出来的消息。 单纯的实现订阅接口但是不重写方法而是自己编写另一个方法就无法实现消息的接收了。

public interface Observers {

	public void update (String message);
}

 

public class Observer implements Observers{
    
    public Observer(Subject s) {
        s.add(this);
    }
    
   //被动订阅
    @Override
    public void update(String message) {
        System.out.println("订阅主题发布的消息:" + message);
    }
   //主动拉取
   //像固定的主题索取消息
     public void updateActive(Subjects sb) {
        if (sb instanceof Subject) {
        System.out.println("订阅者主动向主题拉取数据");
        }
     }

}
View Code

  

 另外java提供了Observer和Observable现成的api可供我们直接使用,setchange的想法也是参考这api的。

虽然说java提供了线程的api类供我们直接使用,但是java提供的observable 是一个实体类 并不是接口,设计原则是针对接口变成,但是java提供的实体类破坏了这个原则。

并且java无法实现多重继承,这样就导致一个子类想公用observable的功能和其他某些超类的功能是就会出现冲突,必须要舍弃一部分。所以通过自己开发的接口可以大大提高灵活度。

而且通过上诉代码应该能自己体验整个流程。所以在正真学会这个模式之后还是推荐自己编写,这样不管是拓展还是修改都很方便!!!

原文地址:https://www.cnblogs.com/culushitai/p/8487047.html