设计模式_极简实现_观察者模式/发布订阅模式

Weil du auch ein Arbeiter bist! / 2023-05-08 / 原文

(在本文的实现中)比起叫观察者模式,似乎叫发布订阅模式更加恰当,因为在这一模式中,Observer并不是主动一方。

这里假定一个场景,油管的油管主(发布者)和观众(订阅者),二者通过平台进行信息的传递(订阅频道、发布视频推送等)。

直接上代码吧。

public interface Subscribers {
    public void update();//收到订阅之后的消息要做什么?
}
public class SubscriberNormal implements Subscribers{
    @Override
    public void update() {
        System.out.println("normal subscribers get latest videos.");//普通观众获得最新视频
    }
}
public class SubscriberVip implements Subscribers{
    @Override
    public void update() {
        System.out.println("vip subscribers get latest videos.");//充值观众获得最新视频
    }
}
abstract class YoutubeChannels {
    ArrayList<Subscribers> subscriber = new ArrayList();//维护订阅者的列表,嗯,还是浅浅耦合了

    public void addSubscriber(Subscribers sbs) {
        this.subscriber.add(sbs);
    }

    public void delSubscriber(Subscribers sbs){
        this.subscriber.remove(sbs);
    }

    protected void notifyObserver(){//把订阅者集合拿过来挨个通知
        for(Subscribers s: subscriber){
            s.update();
        }
    }

    //当然可以用其他顺序让订阅者做其他的事情

    public abstract void publishVideos();//留给不同的发布者自己发挥
}
public class YoutubeNormalChannel extends YoutubeChannels{
    public void publishVideos(){
        System.out.println("normal channels publish new videos.");
        this.notifyObserver();//只发挥了最基本的功能,让订阅者知道更新了
    }
}
public class YoutubePlatform {
    public static void main(String[] args) {
        YoutubeChannels ycs = new YoutubeNormalChannel();
        ycs.addSubscriber(new SubscriberNormal());//在平台上添加订阅者,如果不用此模式,这一步会发生在发布者或者它的抽象中,耦合比较深
        ycs.addSubscriber(new SubscriberVip());//放在这里,发布者实际上不知道自己的订阅者,当然非要知道也不是不行···
        ycs.publishVideos();//发布
    }
}

运行后:

normal channels publish new videos.
normal subscribers get latest videos.
vip subscribers get latest videos.

稍微总结一下:

被观察者/发布者的抽象 YoutubeChannels 中需要维护一个集合存放观察者/订阅者,当然多线程的场景下需要注意线程安全,ArrayList可以回家休息了···

被观察者 YoutubeNormalChannel 可以在其抽象的基础上自定义某些功能,比如说普通频道、官方频道等。它调用了 notifyObserver() 方法,所以通知实际是在这里发出。

观察者/订阅者的抽象 Subscribers 没什么好说的,一堆观察者中最应该被抽象出来的功能就是收到发布之后应该做什么。

观察者/订阅者 SubscriberNormal、SubscriberVip 具体实现了 Subscribers 中的定义的方法,这个方法将在被观察者中被调用。

 

此模式的优点:

  • 观察者和被观察者之间实现松耦合,被观察者知道的信息:观察者是什么类型,与观察者交互使用什么方法。观察者知道的信息:无,只能根据通知做出反应。
  • 观察者可以多个,多类型,可以灵活地被注册和删除,被观察者本身不需要改动,改动放在平台上。