设计模式之观察者(Observer)

编程入门 行业动态 更新时间:2024-10-27 20:23:55

设计模式之<a href=https://www.elefans.com/category/jswz/34/1765125.html style=观察者(Observer)"/>

设计模式之观察者(Observer)

事件处理模型

小朋友睡醒了就哭,饿

写程序模拟这个过程:
v1:最简单的就是写程序一直观察着,什么时候哭了就进行处理

/*** 披着面向对象外衣的面向过程*/
public class Main1 {public static void main(String[] args) {boolean cry = false;while(!cry) {//进行处理}}
}

v2: 面向对象,至少抽象出child类来:

/*** 面向对象的傻等* 一直观察,直到有线程调用了wakeUp方法* 程序没写完,涉及到线程同步,没有写完*/class Child {private boolean cry = false;public boolean isCry() {return cry;}public void wakeUp() {System.out.println("Waked Up! Crying wuwuwuwu...");cry = true;}
}public class Main {public static void main(String[] args) {Child child = new Child();while(!child.isCry()) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("observing...");}}
}

v3: 加入观察者Dad到被观察者Child里面,什么时候醒了,直接调用观察者的方法

/*** 加入观察者*/class Child {private boolean cry = false;private Dad d = new Dad(); //加入观察者Dad到被观察者Child里面public boolean isCry() {return cry;}public void wakeUp() {cry = true;d.feed(); // 直接调用观察者的方法}
}class Dad {public void feed() {System.out.println("dad feeding...");}
}public class Main {public static void main(String[] args) {Child c = new Child();//do sthc.wakeUp();}
}

v4:加入多个观察者,当一个事件发生的时候,每个观察者的处理方式不同

/*** 加入多个观察者*/class Child {private boolean cry = false;// 多个观察者private Dad dad = new Dad();private Mum mum = new Mum();private Dog dog = new Dog();public boolean isCry() {return cry;}public void wakeUp() {cry = true;// 每个观察者的处理方式不同dad.feed();dog.wang();mum.hug();}
}class Dad {public void feed() {System.out.println("dad feeding...");}
}class Mum {public void hug() {System.out.println("mum hugging...");}
}

耦合度太高,观察者的处理方法不一定只适合当前的被观察者,例如小狗汪汪叫这个出来方法,可能也适合于鸡叫的事件
而且添加新的观察者比较麻烦 --> 扩展性不好,耦合度高

v5:分离观察者与被观察者。定义一个Observer接口,里面有actionWeakup方法,指的是小孩醒了之后要采取的动作,不同的观察者实现这Observer个接口

/*** 分离观察者与被观察者*/
class Child {private boolean cry = false;// 将观察者放到list中private List<Observer> observers = new ArrayList<>();{observers.add(new Dad());observers.add(new Mum());observers.add(new Dog());}public boolean isCry() {return cry;}public void wakeUp() {cry = true;// 当wakeup事件发生的时候,遍历观察者进行处理for(Observer o : observers) {o.actionOnWakeUp();}}
}// 定义一个Observer接口
interface Observer {void actionOnWakeUp();
}//不同的观察者实现这个Observer接口  
class Dad implements Observer {public void feed() {System.out.println("dad feeding...");}@Overridepublic void actionOnWakeUp() {feed();}
}class Mum implements Observer {public void hug() {System.out.println("mum hugging...");}@Overridepublic void actionOnWakeUp() {hug();}
}class Dog implements Observer {public void wang() {System.out.println("dog wang...");}@Overridepublic void actionOnWakeUp() {wang();}
}public class Main {public static void main(String[] args) {Child c = new Child();//do sthc.wakeUp();}
}

一个事件发生,会经过一系列的观察者的处理,这个事件才算完成

v5:一个事件发生之后,观察者需要根据事件的具体情况,做出处理。例如小孩哭的厉不厉害,时间等
该怎么把小孩哭的事件的具体情况传递给观察者呢?
封装一个事件类,事件的所有情况都在事件里面:

/*** 有很多时候,观察者需要根据事件的具体情况来进行处理*/class Child {private boolean cry = false;private List<Observer> observers = new ArrayList<>();{observers.add(new Dad());observers.add(new Mum());observers.add(new Dog());}public boolean isCry() {return cry;}public void wakeUp() {cry = true;// 醒了之后,创建一个事件对象wakeUpEvent event = new wakeUpEvent(System.currentTimeMillis(), "bed");// 事件对象传递给观察者for(Observer o : observers) {o.actionOnWakeUp(event);}}
}//事件类 fire Event
class wakeUpEvent{long timestamp;String loc;public wakeUpEvent(long timestamp, String loc) {this.timestamp = timestamp;this.loc = loc;}
}// 事件的所有情况都在事件里面,封装好传给观察者
interface Observer {void actionOnWakeUp(wakeUpEvent event);
}// Observer里面可以写if,判断event的情况,来进行处理,这块代码里面为了简便就没写
class Dad implements Observer {public void feed() {System.out.println("dad feeding...");}@Overridepublic void actionOnWakeUp(wakeUpEvent event) {feed();}
}class Mum implements Observer {public void hug() {System.out.println("mum hugging...");}@Overridepublic void actionOnWakeUp(wakeUpEvent event) {hug();}
}class Dog implements Observer {public void wang() {System.out.println("dog wang...");}@Overridepublic void actionOnWakeUp(wakeUpEvent event) {wang();}
}public class Main {public static void main(String[] args) {Child c = new Child();//do sthc.wakeUp();}
}

观察者模式三要素:
Source事件源对象 --> 是谁发出的事件
Observer观察者 --> 是谁在等着这个事件
Event事件 --> 事件本身
事件源对象有一堆的观察者观察着它,当事件源对象发出事件的时候,观察者会对事件进行处理

V7:一个事件源可以发出不同的事件,一个事件也可以被多个观察者处理,大多数时候,我们处理事件的时候,需要事件源对象
为什么需要事件源对象:因为有时候需要根据事件源对象的不同,采用不同的处理方法。
Sping的AOP其实可以语义上理解成观察者模式,在程序执行的过程中,弄一个切面,当代码执行到这个切面的时候,先执行指定好的一系列方法,
然后继续往下,这就相当于观察者模式,观察着这个切面,当到达这个切面的时候,先执行一系列定义好的方法

/*** 有很多时候,观察者需要根据事件的具体情况来进行处理* 大多数时候,我们处理事件的时候,需要事件源对象*/class Child {private boolean cry = false;private List<Observer> observers = new ArrayList<>();{observers.add(new Dad());observers.add(new Mum());observers.add(new Dog());}public boolean isCry() {return cry;}public void wakeUp() {cry = true;wakeUpEvent event = new wakeUpEvent(System.currentTimeMillis(), "bed", this);for(Observer o : observers) {o.actionOnWakeUp(event);}}
}class wakeUpEvent{long timestamp;String loc;// 将事件源对象,绑定到事件本身Child source;public wakeUpEvent(long timestamp, String loc, Child source) {this.timestamp = timestamp;this.loc = loc;this.source = source;}// 往往事件对象都会有一个getSource方法,例如系统提供的WindowEventpublic Child getSource() {return this.source;}
}interface Observer {void actionOnWakeUp(wakeUpEvent event);
}class Dad implements Observer {public void feed() {System.out.println("dad feeding...");}@Overridepublic void actionOnWakeUp(wakeUpEvent event) {feed();}
}class Mum implements Observer {public void hug() {System.out.println("mum hugging...");}@Overridepublic void actionOnWakeUp(wakeUpEvent event) {hug();}
}class Dog implements Observer {public void wang() {System.out.println("dog wang...");}@Overridepublic void actionOnWakeUp(wakeUpEvent event) {wang();}
}public class Main {public static void main(String[] args) {Child c = new Child();//do sthc.wakeUp();}
}

v8:java里面的事件继承自EventObject这个类。
这里也自己定义了一个事件类,里面有getSource方法
钩子函数,hook,callback,listener都是观察者模式,都是一回事

/*** 有很多时候,观察者需要根据事件的具体情况来进行处理* 大多数时候,我们处理事件的时候,需要事件源对象* 事件也可以形成继承体系*/
class Child {private boolean cry = false;private List<Observer> observers = new ArrayList<>();{observers.add(new Dad());observers.add(new Mum());observers.add(new Dog());// 钩子函数hook,钩在那里,当事件发生的时候,钩子函数被执行// 钩子函数就是Observer模式// 传过去的是个函数observers.add((e)->{System.out.println("ppp");});//hook callback function}public boolean isCry() {return cry;}public void wakeUp() {cry = true;wakeUpEvent event = new wakeUpEvent(System.currentTimeMillis(), "bed", this);for(Observer o : observers) {o.actionOnWakeUp(event);}}
}
// 定义抽象Event方法,里面有getSource方法
abstract class Event<T> {abstract T getSource();
}class wakeUpEvent extends Event<Child>{long timestamp;String loc;Child source;public wakeUpEvent(long timestamp, String loc, Child source) {this.timestamp = timestamp;this.loc = loc;this.source = source;}@OverrideChild getSource() {return source;}
}interface Observer {void actionOnWakeUp(wakeUpEvent event);
}class Dad implements Observer {public void feed() {System.out.println("dad feeding...");}@Overridepublic void actionOnWakeUp(wakeUpEvent event) {feed();}
}class Mum implements Observer {public void hug() {System.out.println("mum hugging...");}@Overridepublic void actionOnWakeUp(wakeUpEvent event) {hug();}
}class Dog implements Observer {public void wang() {System.out.println("dog wang...");}@Overridepublic void actionOnWakeUp(wakeUpEvent event) {wang();}
}public class Main {public static void main(String[] args) {Child c = new Child();//do sthc.wakeUp();}
}

v9:java jwt里面用了观察者模式,点击button,所有的观察者listener会被触发

public class TestFrame 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(){@Overridepublic void windowClosing(WindowEvent e) {System.exit(0);}});this.setLocation(400, 400);this.setVisible(true);}public static void main(String[] args) {new TestFrame().launch();}private class MyActionListener implements ActionListener { //Observerpublic 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!");}}
}

jvm运行着,监听着操作系统的键盘事件,当按键发生的时候,jvm会创建好KeyEvent事件

js里面也有event对象,事件源对象是event.traget。当按下button的时候,会自动生成event对象,把事件源对象传过去

在很多系统中,Observer模式往往和责任链共同负责对于事件的处理,其中的某一个observer负责是否将事件进一步传递
Observer不存在往回传的情况 --> 责任链部分讲到

更多推荐

设计模式之观察者(Observer)

本文发布于:2023-11-15 21:55:53,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1606955.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:观察者   模式   Observer

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!