观察者模式介绍
观察者模式又被叫做发布订阅模式。观察者模式在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博客作者刺激乐天派的原创作品,如需转载,请注明出处,否则将追究法律责任