设计模式Observer 观察者模式浅析
Posted 行百里er
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式Observer 观察者模式浅析相关的知识,希望对你有一定的参考价值。
Observer模式:事件处理模型
事件处理模型经常使用Observer+责任链
军情观察室
朝鲜生气了,后果不太严重。中美俄等国一直对朝鲜暗中观察,就朝鲜的一系列活动各自采取措施。
在
被观察者
朝鲜周围,有多双眼睛正观察着它呢,这些观察者
有中国、美国、俄罗斯等等。。
当朝鲜有活动时,这些观察者会采取相应的活动。
用代码构造一下这个场景:
public class Client {
public static void main(String[] args) {
Korea k = new Korea();
k.fire();
}
}
class Korea {
China china = new China();
Usa usa = new Usa();
public void fire () {
System.out.println("朝鲜:发射核弹!");
china.warn();
usa.threaten();
}
}
class China {
public void warn () {
System.out.println("中国:不要在我家门口玩火,否则后果自负!");
}
}
class Usa {
public void threaten () {
System.out.println("美国:韩国小老弟来我们军事演练走一波!");
}
}
运行结果:
朝鲜:发射核弹!
中国:不要在我家门口玩火,否则后果自负!
美国:韩国小老弟来我们军事演练走一波!
上面这段代码的弊端是显而易见的,因为这里的观察者
不止中国、美国,还有日本、俄罗斯等等,如果继续加入观察者,将会在被观察者类Korea
中继续添加代码,耦合度太高,不易扩展!
观察者模式
上面的模型其实就用到了
观察者模式
的思想,观察者针对被观察者的行为动作
做出相应的处理。由于耦合度高,我们可以分离观察者和被观察者。有很多时候,观察者需要根据事件的具体情况来进行处理,而且我们处理事件的时候,需要事件源对象。
观察者
中国、美国等需要对被观察者
朝鲜的具体动作时间进行处理,朝鲜就是发出事件的事件源
对象。
代码升级了:
public class Client {
public static void main(String[] args) {
Korea k = new Korea();
k.fire();
}
}
class Korea {
private List<Observer> observers = new ArrayList<>();
{
observers.add(new China());
observers.add(new Usa());
}
public void fire () {
System.out.println("朝鲜:我要发射了!Boom!!!");
//事件发生了
FireEvent fireEvent = new FireEvent(System.currentTimeMillis(), "夏威夷", this);
observers.forEach(observer -> observer.onFire(fireEvent));
}
}
/**
* 抽象出事件类
* @param <T>
*/
abstract class Event<T> {
abstract T getSource();
}
/**
* 发射核弹事件,事件源是Korea
*/
class FireEvent extends Event<Korea> {
//事件发生时间
long timestamp;
//事件发生地点
String location;
//事件源
private Korea korea;
public FireEvent(long timestamp, String location, Korea korea) {
this.timestamp = timestamp;
this.location = location;
this.korea = korea;
}
@Override
public Korea getSource() {
return korea;
}
}
/**
* 观察者
*/
interface Observer {
//观察者根据事件作出响应
void onFire(FireEvent fireEvent);
}
class China implements Observer {
public void warn () {
System.out.println("中国:不要在我家门口玩火,否则后果自负!");
}
@Override
public void onFire(FireEvent fireEvent) {
if (fireEvent.location.contains("鸭绿江")) {
warn();
}
}
}
class Usa implements Observer {
public void threaten () {
System.out.println("美国:韩国小老弟来我们军事演练走一波!");
}
@Override
public void onFire(FireEvent fireEvent) {
if (fireEvent.location.contains("夏威夷")) {
threaten();
}
}
}
运行结果:
朝鲜:我要发射了!Boom!!!
美国:韩国小老弟来我们军事演练走一波!
可以看到,观察者只根据事件源Korea
的事件发射,位置夏威夷
做出了时间响应!
而且,有没有发现,被观察者里面有一个List<Observer> observers
,很像责任链模式
对吧?观察者模式的事件处理模型通常是Observer+责任链的。
随处可见的观察者
javascript的onclick
<script>
function cb(event){
alert(event);
}
</script>
<input type="button" onclick="cb(this)" value="点我!" />
监听点击事件,做出事件响应
jdk awt包下的Button等
public class MyFrame extends Frame {
public void launch() {
Button b = new Button("press me");
b.addActionListener(new MyActionListener());
b.addActionListener(new MyActionListener2());
this.add(b);
this.pack();
this.addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.setLocation(400, 400);
this.setVisible(true);
}
public static void main(String[] args) {
new MyFrame().launch();
}
private class MyActionListener implements ActionListener { //Observer
public void actionPerformed(ActionEvent e) {
((Button)e.getSource()).setLabel("press me again!");
System.out.println("button pressed!");
}
}
private class MyActionListener2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("button pressed 2!");
}
}
}
这里的ActionListener
就是观察者。
我们平时遇到的钩子函数,回调函数,Observer,甚至一些Listener,其实都是观察者模式的体现。
观察者模式的通用类图
参考《设计模式之禅》
-
Subject被观察者
定义被观察者必须实现的职责,它必须能够动态地增加、取消观察者。它一般是抽象类或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观察者。
-
Observer观察者
观察者接收到消息后,即进行update(更新方法)操作,对接收到的信息进行处理。
-
ConcreteSubject具体的被观察者
定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。
-
ConcreteObserver具体的观察者
每个观察在接收到消息后的处理反应是不同,各个观察者有自己的处理逻辑。
小结
-
观察者模式是松偶合的。改变主题或观察者中的一方,另一方不会受到影响。 -
JDK中也有自带的观察者模式。但是被观察者是一个类而不是接口,限制了它的复用能力。
Observer
java.util
public interface Observer
A class can implement the Observer interface when it wants to be informed of changes in observable objects.
void update(Observable o, Object arg)
Observable
java.util
Class Observable
-
在JavaBean和Swing中也可以看到观察者模式的影子。
熬夜不易,欢迎关注转发、点赞、在看,给个鼓励,谢谢大伙!
也欢迎多踩踩我的博客:https://blog.csdn.net/hundred_li_journey
以上是关于设计模式Observer 观察者模式浅析的主要内容,如果未能解决你的问题,请参考以下文章
[Android&Java]浅谈设计模式-代码篇:观察者模式Observer
设计模式之- 观察者模式(Observer Pattern)