Observer观察者模式是Java23种设计模式中的一种,也是一个事件处理模型。
这里通过一个生活中的小事来了解Observer观察者模式。这个设计模式十分的重要,企业中的事件处理通常是观察者与责任链结合来完成设计。
先了解需求:
有一个小婴儿,正在床上睡着,突然他醒了并且大哭起来,他的爸爸赶紧给他喂奶。模拟这个事件的过程。
这次,我们通过逐步进行完善的方式写了7个版本的代码,循序渐进的讲解了Observer观察者模式中观察者与被观察者的各种关系及操作。
最后感谢大家的关注
欢迎添加qq 1723082823 进入我们的粉丝群 获取更多更新视频资料!
第一个版本
/**
* 披着面向对象外衣的面向过程
*/
public class Main {
public static void main(String[] args) {
boolean cry = false;
while(!cry) {
//进行处理
}
}
}
第二个版本
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...");
}
}
}
在这个版本中,已经可以看到面向对象进行编程的实际情况了。将可以抽象出来的类设置出来代表婴儿,并且为这个类添加方法。在主方法中设置一个循环,一直等待婴儿哭的事件发生,效率低下。
第三个版本
class Child {
private boolean cry = false;
private Dad d = new Dad(); //私有一个婴儿爸爸的对象
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 sth
c.wakeUp(); //不需要循环判断是否哭了
}
}
最后感谢大家的关注
欢迎添加qq 1723082823 进入我们的粉丝群 获取更多更新视频资料!
这个版本的实例就是将婴儿爸爸喂奶的动作加入到婴儿的醒事件中,这时,只要婴儿睡醒就会自动调用他爸爸的喂奶的方法,不用for循环一直等待浪费时间了。
==>>这个版本中加入了 观察者,并且将观察者的方法加入到被观察者中,当被观察者的事件发生时,就会直接调动观察者的动作,省去了一直等待的时间浪费。
第四个版本
现实生活中,一个婴儿哭了之后,可能会有很多的情况发生,比如:他妈妈抱着哄他,他爸爸给他喂奶,他奶奶听见孩子哭到他爸妈屋问孩子怎么哭了?等等。
所以这个版本中我们添加了多个观察者。
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...");
}
}
class Dog {
public void wang() {
System.out.println("dog wang...");
}
}
public class Main {
public static void main(String[] args) {
Child c = new Child();
//do sth
c.wakeUp();
}
}
最后感谢大家的关注
欢迎添加qq 1723082823 进入我们的粉丝群 获取更多更新视频资料!
虽然现在的编程更接近现实,但是还是有缺点:如果要添加一个新的观察者会很麻烦,而且观察者的事件与婴儿的事件耦合太紧密。
第五个版本
在这个版本中,解决上个版本中存在的耦合度太高的问题。
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;
for(Observer o : observers) {
o.actionOnWakeUp();
}
}
}
interface Observer { //设计一个接口
void actionOnWakeUp(); //存储当婴儿醒了之后所做的动作
}
class Dad implements Observer { //所有观察者实现Observer接口
public void feed() {
System.out.println("dad feeding...");
}
@Override //重写接口中的方法
public void actionOnWakeUp() {
feed();
}
}
class Mum implements Observer {
public void hug() {
System.out.println("mum hugging...");
}
@Override
public void actionOnWakeUp() {
hug();
}
}
class Dog implements Observer {
public void wang() {
System.out.println("dog wang...");
}
@Override
public void actionOnWakeUp() {
wang();
}
}
public class Main {
public static void main(String[] args) {
Child c = new Child();
//do sth
c.wakeUp();
}
}
到此为止我们做的已经很多了,现在我们考虑一下,如何根据被观察发生的具体事件,让不同的观察者去进行处理。
第六个版本
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);
}
}
}
//事件类 表示婴儿睡醒这个事件
class wakeUpEvent{
long timestamp;
String loc;
public wakeUpEvent(long timestamp, String loc) {
this.timestamp = timestamp;
this.loc = loc;
}
}
interface Observer {
void actionOnWakeUp(wakeUpEvent event);
}
class Dad implements Observer {
public void feed() {
System.out.println("dad feeding...");
}
@Override
public void actionOnWakeUp(wakeUpEvent event) {
feed();
}
}
class Mum implements Observer {
public void hug() {
System.out.println("mum hugging...");
}
@Override
public void actionOnWakeUp(wakeUpEvent event) {
hug();
}
}
class Dog implements Observer {
public void wang() {
System.out.println("dog wang...");
}
@Override
public void actionOnWakeUp(wakeUpEvent event) {
wang();
}
}
public class Main {
public static void main(String[] args) {
Child c = new Child();
//do sth
c.wakeUp();
}
}
- 在Observer观察者模式中
Event是必须要有的,Source是事件源对象、被观察者,Listener是事件观察者,Event是事件本身。
事件源对象拥有很多的观察者,会发出具体的Event,Observer观察到Event的时候,作出具体的反应actionOnEvent。
第七个版本
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;
}
}
interface Observer {
void actionOnWakeUp(wakeUpEvent event);
}
class Dad implements Observer {
public void feed() {
System.out.println("dad feeding...");
}
@Override
public void actionOnWakeUp(wakeUpEvent event) {
feed();
}
}
class Mum implements Observer {
public void hug() {
System.out.println("mum hugging...");
}
@Override
public void actionOnWakeUp(wakeUpEvent event) {
hug();
}
}
class Dog implements Observer {
public void wang() {
System.out.println("dog wang...");
}
@Override
public void actionOnWakeUp(wakeUpEvent event) {
wang();
}
}
public class Main {
public static void main(String[] args) {
Child c = new Child();
//do sth
c.wakeUp();
}
}
在事件(wakeUpEvent)中封装了Child source(源对象)
当需要source时就可以直接把source get出来,不需要时就不用
最后感谢大家的关注
欢迎添加qq 1723082823 进入我们的粉丝群 获取更多更新视频资料!