手记

JAVA设计模式之观察者模式

观察者模式介绍

观察者模式又被叫做发布订阅模式。观察者模式在Java中非常的常见,比如说Spring中的事件监听设计就是观察者模式,再比如说Redis、kafka的发布订阅功能就是观察者模式。

应用场景

观察者模式在应用上非常广泛,比如订阅推送,发布订阅功能,聊天场景,微信公众号订阅等非常多。这个模式说白了就是:被观察者(发布者)生产内容,观察者(订阅者)获取内容。比如说订阅推送,假如我的博客发了一篇新的文章,那么那些关注我的人就会收到推送的消息。再比如说51CTO的付费专栏,如果专栏作者发布了新的专栏内容,那么那些订阅了该作者该专栏的人就会收到专栏推送的消息。而聊天分为一对一和一对多,一对一是私聊模式,而一对多是群聊模式,他们都是观察者模式。

观察者模式类图

JAVA设计模式之观察者模式

实现订阅专栏功能

1.Observer接口

/**

 * @ClassName Observer

 * @Description TODO:描述该接口职责

 * @Author ckmike

 * @Date 18-12-7 下午3:00

 * @Version 1.0

 * @Copyright ckmike

 **/

public interface Observer {

    void update(String message);

}

2.Observerable接口

/**

 * @ClassName Observerable

 * @Description TODO:描述该接口职责

 * @Author ckmike

 * @Date 18-12-7 下午2:56

 * @Version 1.0

 * @Copyright ckmike

 **/

public interface Observerable {

    // 注册观察者

    void register(Observer observer);

    // 注销观察者

    void remove(Observer observer);

    void notifyObserver();

}

3.SubscriptionChannel类

/**

 * SubscriptionChannel 简要描述

 * <p> TODO:描述该类职责 </p>

 *

 * @author ckmike

 * @version 1.0

 * @date 18-12-7 下午3:04

 * @copyright ckmike

 **/

public class SubscriptionChannel implements Observerable{

    List<Observer> observers;

    private String message;

    public SubscriptionChannel() {

        this.observers = new ArrayList<Observer>();

    }

    @Override

    public void register(Observer observer) {

        this.observers.add(observer);

    }

    @Override

    public void remove(Observer observer) {

        this.observers.remove(observer);

    }

    @Override

    public void notifyObserver() {

        // 通知所有observer

        for(Observer observer: this.observers){

            observer.update(message);

        }

    }

    public void sendMessage(String message) {

        this.message = message;

        System.out.println("专栏作者更新专栏文章......");

        // 调用通知所有订阅者

        notifyObserver();

    }

}

4.User类

/**

 * User 简要描述

 * <p> TODO:描述该类职责 </p>

 *

 * @author ckmike

 * @version 1.0

 * @date 18-12-7 下午3:13

 * @copyright ckmike

 **/

public class User implements Observer {

    private String name;

    private String message;

    public User(String name) {

        this.name = name;

    }

    @Override

    public void update(String message) {

        this.message = message;

        // 这里应该写到数据库中的,但我们这里就直接输出吧,方便

        read();

    }

    public void read() {

        System.out.println(name+"收到推送消息:"+this.message);

    }

}

5.测试用例

/**

 * Test 简要描述

 * <p> TODO:描述该类职责 </p>

 *

 * @author ckmike

 * @version 1.0

 * @date 18-12-7 下午3:19

 * @copyright ckmike

 **/

public class Test {

    public static void main(String[] args) {

        // 订阅专栏

        SubscriptionChannel channel = new SubscriptionChannel();

        // 三个用户

        Observer user = new User("Mike");

        Observer user1 = new User("William");

        Observer user2 = new User("Crane");

        // 用户订阅专栏,开启一个线程进行订阅

        new Thread(()->{

            // 假设读者订阅付费的间隔是10s

            try {

                channel.register(user);

                TimeUnit.SECONDS.sleep(5);

                channel.register(user1);

                TimeUnit.SECONDS.sleep(5);

                channel.register(user2);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }).start();

        // 专栏作者线程进行发布文章,每隔一秒发布一篇文章

        new Thread(()->{

            int i = 1;

            while (true){

                channel.sendMessage("JAVA设计模式之观察者模式!-第"+i+"章");

                try {

                    TimeUnit.SECONDS.sleep(5);

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

                i++;

                if(i>5){

                    break;

                }

            }

        }).start();

        // 中途有用户退出订阅专栏,同时有人加入订阅

        new Thread(()->{

            try {

                TimeUnit.SECONDS.sleep(7);

                channel.remove(user1);

                TimeUnit.SECONDS.sleep(5);

                channel.register(new User("Nill"));

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }).start();

    }

}

JAVA设计模式之观察者模式

那么到这里我们就实现了订阅专栏消息推送。是不是很简单。那么我这里再给大家提供两个思考问题:1.如何让后来订阅的读者能够收到作者之前发布的消息呢?2.Spring的事件监听是如何实现的呢?如果你想到了欢迎在下面留言分析,和大家讨论哟。好!打完收工!

©著作权归作者所有:来自51CTO博客作者刺激乐天派的原创作品,如需转载,请注明出处,否则将追究法律责任


0人推荐
随时随地看视频
慕课网APP