6.[研磨设计模式笔记]观察者模式

简介:

1.定义

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。

2.解决问题

——订阅报纸

181331406.png

看起来订阅者是直接根有据打交道,但实际上,订阅者的订阅数据是被邮寄传递到报社,当报社出了报纸,报社按订阅信息交给邮局,邮局在代为发送到订阅者手里。在整个过程中,邮局起到一个中转的作用。

使用观察者模式来解决问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public  class  Subject {
     private  List<Observer> readers =  new  ArrayList<Observer>();
     public  void  attach(Observer reader) {
         readers.add(reader);
     }
     public  void  detach(Observer observer) {
         readers.remove(observer);
     }
     protected  void  notifyObservers() {
         for  (Observer reader : readers)
             reader.update( this );
     }
}
public  class  NewsPaper  extends  Subject {
     private  String content;
     public  String getContent() {
         return  content;
     }
     public  void  setContent(String content) {
         this .content = content;
         super .notifyObservers();
     }
}
public  interface  Observer {
     public  void  update(Subject subject);
}
public  class  Reader  implements  Observer {
     private  String name;
     public  void  update(Subject subject) {
         name = ((NewsPaper)subject).getContent();
         System.out.println(name);
     }
}
public  class  Client {
     public  static  void  main(String[] args) {
         // 创建一个报纸,作为目标
         NewsPaper subject =  new  NewsPaper();
         // 创建一个读者
         Reader reader1 =  new  Reader();
         Reader reader2 =  new  Reader();
         // 注册订阅者
         subject.attach(reader1);
         subject.attach(reader2);
         // 要出报纸啦
         subject.setContent( "New" );
     }
}

3.模式讲解

上述问题中订阅者最关心的问题时是何时能收到最新处的报纸,但要是报纸出版的时间不固定怎么办?进一步抽象这个问题:当一个对象的状态发生改变的时候,如果让依赖于它的所有对象得到通知,并进行相应的处理呢?

解决思路

这是一个典型一对多的对象关系,一个报纸对象,有很多个订阅者对象来订阅,当报纸出版的时候,也就是报纸对象改变的时候。观察者模式处理这种问题时,把这多个订阅者称为观察者:Observer,多个观察者观察的对象称为目标:Subject。

一个目标可以有任意多个观察者独享,一旦目标的状态发生改变,所有注册的观察者都会得到通知,然后各个观察者会对通知做出相应的响应,执行相应的业务功能处理,并使自己的状态与目标状态保持一致。

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public  class  Subject {
     // 用来保存注册的观察者对象
     private  List<Observer> observers =  new  ArrayList<Observer>();
     // 注册观察者对象
     public  void  attach(Observer observer) {
         observers.add(observer);
     }
     // 删除观察者对象
     public  void  detach(Observer observer) {
         observers.remove(observer);
     }
     // 通知所有注册的观察者对象
     protected  void  notifyObservers() {
         for  (Observer observer : observers)
             observer.update( this );
     }
}
public  class  ConcreteSubject  extends  Subject {
     private  String subjectState;
     public  String getSubjectState() {
         return  subjectState;
     }
     public  void  setSubjectState(String subjectState) {
         this .subjectState = subjectState;
         // 状态改变了,通知各个观察者
         this .notifyObservers();
     }
}
public  interface  Observer {
     public  void  update(Subject subject);
}
public  class  ConcreteObserver  implements  Observer {
     private  String observerState;
     public  void  update(Subject subject) {
         // 可能需要更新观察者状态,使其与目标的状态保持一致
         observerState = ((ConcreteSubject) subject).getSubjectState();
     }
}

应用范围

按照模式的定义,目标和观察者之间是典型的一对多关系。但如果观察者只有一个,也是可以的;同样,一个观察者也可以观察多个目标。

单向依赖

在观察者模式中,观察者和目标是单向依赖,只有观察者依赖于目标,而目标不能依赖与观察者。

观察者模式调用顺序示意图

在使用观察者模式时,分为两个阶段:

第一个阶段是准备阶段,即维护目标和观察者关系的阶段;

181637861.png

第二阶段是实际运行阶段。

181644209.png

推模式和拉模式

推模式:目标对象主动向观察者推送目标的详细信息,不管观察者是否需要,推送的信息通常是目标对象的全部或部分数据,相当于广播通信。

拉模式:目标对象在通知观察者的时候,只传递少量信息,如果观擦或者需要更具体的信息,由观察者主动到目标对象中获取,相当于观察者从目标对象中拉数据。

Java观察者模式

java.util包里有一个Observable类,还有一个接口Observer,其中定义了update方法,就是观察者接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public  class  NewsPaper  extends  java.util.Observable {
     private  String content;
     public  String getContent() {
         return  content;
     }
     public  void  setContent(String content) {
         this .content = content;
         // 注意在Java中Observer模式的时候,下边这句不可少
         this .setChanged();
         // 然后主动通知,这里用的推模式
         this .notifyObservers( this .content);
     }
}
public  class  Reader  implements  java.util.Observer {
     private  String name;
     public  void  update(Observable o, Object obj) {
         // 这是采用推的方式
         System.out.println(name + obj);
         // 这是采用拉的方式
         System.out.println(name + ((NewsPaper) o).getContent());
     }
}
public  class  Client {
     public  static  void  main(String[] args) {
         // 创建一个报纸,作为目标
         NewsPaper subject =  new  NewsPaper();
         // 创建一个读者
         Reader reader1 =  new  Reader();
         Reader reader2 =  new  Reader();
         // 注册订阅者
         subject.addObserver(reader1);
         subject.addObserver(reader2);
         // 要出报纸啦
         subject.setContent( "New" );
     }
}

适配器模式的优缺点:

优点:实现了观察者和目标之间的抽象耦合,实现了动态联动,支持广播通信

缺点:可能会引起无谓的操作

4.思考

观察者模式的本质是:触发联动

当修改目标对象的状态时,就会触发相应的通知,然后会循环调用所有注册的观擦或者对象的相应方法,其实就相当于联动调用这些观察者的方法。

何时选用适配器模式

当一个抽象模型有两个方面,其中一个方面的操作依赖于另一个方面的状态变化,可以选用观察者模式;

如果在更改一个对象的时候,需要同时连带改变其他的喜爱那个,而且不知道究竟应该有多少对象需要被连带改变,可以选用观察者模模式;

当一个对象必须通知其他对象,但是有希望这个对象和其他被通知的对象是松散耦合的,即这个对象其实不想知道具体被通知的对象,可以选用观察者模式。











本文转自 LinkedKeeper 51CTO博客,原文链接:http://blog.51cto.com/sauron/1230190,如需转载请自行联系原作者
目录
相关文章
|
3月前
|
设计模式 监控 安全
设计模式 | 观察者模式
设计模式 | 观察者模式
18 0
|
3月前
|
设计模式 前端开发 数据中心
设计模式之观察者模式
设计模式之观察者模式
|
2月前
|
设计模式 前端开发 JavaScript
观察者模式 vs 发布-订阅模式:两种设计模式的对决!
欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚刚开始学习前端的读者们打造的。无论你是初学者还是有一些基础的开发者,我们都会在这里为你提供一个系统而又亲切的学习平台。我们以问答形式更新,为大家呈现精选的前端知识点和最佳实践。通过深入浅出的解释概念,并提供实际案例和练习,让你逐步建立起一个扎实的基础。无论是HTML、CSS、JavaScript还是最新的前端框架和工具,我们都将为你提供丰富的内容和实用技巧,帮助你更好地理解并运用前端开发中的各种技术。
|
3天前
|
设计模式 Java
【设计模式系列笔记】抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是一种设计模式,属于创建型模式之一。它提供了一种方式来创建一系列相关或相互依赖的对象,而无需指定它们具体的类。抽象工厂模式通过引入抽象的工厂接口,使得客户端代码可以使用抽象的接口来创建一组相关的产品,而不关心这些产品的具体实现。
97 4
|
16天前
|
设计模式 监控 Java
设计模式 - 观察者模式(Observer):Java中的战术与策略
【4月更文挑战第7天】观察者模式是构建可维护、可扩展系统的关键,它在Java中通过`Observable`和`Observer`实现对象间一对多的依赖关系,常用于事件处理、数据绑定和同步。该模式支持事件驱动架构、数据同步和实时系统,但需注意避免循环依赖、控制通知粒度,并关注性能和内存泄漏问题。通过明确角色、使用抽象和管理观察者注册,可最大化其效果。
|
1月前
|
设计模式 存储 Java
【设计模式】观察者模式
【设计模式】观察者模式
|
2天前
|
设计模式 Java 容器
【设计模式系列笔记】组合模式
组合模式(Composite Pattern)是一种结构型设计模式,它允许将对象组合成树状结构以表示部分-整体的层次结构。组合模式使得客户端可以统一处理单个对象和对象组合,而无需区分它们的类型。
33 12
|
2天前
|
设计模式
【设计模式系列笔记】桥接模式
桥接模式(Bridge Pattern)是一种结构性设计模式,它将抽象部分与实现部分分离,使它们可以独立变化而互不影响。桥接模式通过组合而不是继承的方式来实现这种分离。
24 6
|
3月前
|
设计模式 Java Spring
设计模式之观察者模式
设计模式之观察者模式
26 0
|
3月前
|
设计模式 算法 自动驾驶
常见的设计模式(模板与方法,观察者模式,策略模式)
随着时间的推移,软件代码越来越庞大,随着而来的就是如何维护日趋庞大的软件系统。在面向对象开发出现之前,使用的是面向过程开发来设计大型的软件程序,面向过程开发将软件分成一个个单独的模块,模块之间使用函数进行组合,最后完成系统的开发,每次需要修改软件,如果不涉及好各个模块的关系,就会导致软件系统难以维护,从而导致软件变得不可使用。面向对象方法用对象模拟问题域中的实体,以对象间的联系刻画实体间联系
63 2