一.概念
观察者模式是一种常见的设计模式,用于在对象之间建立一对多的依赖关系。在该模式中,一个主题(被观察者)维护了一个观察者列表,并在自身状态发生变化时通知所有观察者进行相应的更新。
二.观察者模式角色
-
抽象被观察者角色: 定义了动态增加、删除以及通知观察者对象的方法,职责就是管理和通知观察者。持有观察者对象的集合。
-
**具体被观察者角色:**一般继承抽象被观察者,实现自己本身的业务逻辑,当状态发生改变时发起通知。
-
**抽象观察者角色:**提供一个接口,定义了观察者收到通知时更新自己的方法。
-
**具体观察者角色:**实现抽象观察者接口,处理不同具体观察者的不同业务逻辑。
三.优缺点
1.优点
1.解耦:观察者模式将被观察者和观察者解耦,使它们可以独立地进行扩展和修改,而不会影响到彼此。
2.松散耦合:被观察者只需要知道观察者接口而不需要了解具体观察者的实现,从而降低了彼此之间的依赖程度,实现了松散耦合。
3.可重用性:观察者模式可增加新的观察者或被观察者,无需修改原有代码,提高了代码的可重用性。
2.缺点
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
- 如果观察者太多,被观察者通知观察者消耗的时间很多,影响系统的性能。
- 当观察者集合中的某一观察者错误时就会导致系统卡壳,因此一般会采用异步方式。
四.使用场景
1.当一个对象的改变需要同时通知其他多个对象,并且这些对象的更新操作可能不同步时,可以使用观察者模式。
2.当一个对象的状态变化需要引起其他相关对象的状态变化时,可以使用观察者模式来保持对象之间的一致性。
3.当系统中存在一个主体对象和多个观察者对象之间的动态关系,并且希望避免对象之间的紧耦合关系时,可以使用观察者模式。
4.当一个对象需要将自己的状态变化通知给一组观察者,同时这些观察者对象具有不同的行为和角色时,可以使用观察者模式。
总结来说,观察者模式适用于多个对象之间存在一对多的依赖关系,当一个对象的状态变化需要通知其他对象并进行相应处理时,观察者模式能够提供一种松散耦合的解决方案,增加系统的灵活性和可扩展性。
五.实现
1.场景
灰太狼具有被观察者属性,喜洋洋这些羊咩咩一直都在观察者灰太狼,所以羊咩咩们是观察者。OK,角色确定了,看看具体是怎么实现的...
2.抽象被观察者
java
public abstract class Subject {
/**
* 观察者对象的集合
*/
private List<Observer> observerList = new ArrayList<>();
/**
* 登记观察者
*
* @param observer
*/
public void attach(Observer observer) {
observerList.add(observer);
System.out.println("增加了观察者:" + observer.getName());
}
/**
* 删除观察者
*
* @param observer
*/
public void dettach(Observer observer) {
observerList.remove(observer);
System.out.println("删除了观察者:" + observer.getName());
}
/**
* 通知所有观察者
*/
public void notifyObserver() {
for (Observer observer : observerList) {
observer.update("灰太狼要搞事情了");
}
}
}
3.创建被观察者对象
灰太狼是具体被观察者,继承抽象被观察者
java
public class Wolf extends Subject {
public void invade(){
System.out.println("灰太狼:我要搞事情了");
// 通知所有观察者
notifyObserver();
}
}
4.抽象观察者
java
public interface Observer {
String getName();
/**
* 通知更新方法
*
* @param msg
*/
public void update(String msg);
}
5.创建观察者对象
喜羊羊是具体观察者
java
public class PleasantSheep implements Observer{
@Override
public String getName() {
return "喜羊羊";
}
/**
* 具体业务逻辑
*/
@Override
public void update(String msg) {
System.out.println("喜羊羊收到通知:" + msg);
}
}
6.测试
接下来看客户端如何把观察者模式跑起来
java
public class Client {
public static void main(String[] args) {
// 灰太狼--被观察者
Wolf wolf = new Wolf();
// 喜羊羊--观察者
Observer pleasantSheep = new PleasantSheep();
// 登记观察者
wolf.attach(pleasantSheep);
// 灰太狼入侵
wolf.invade();
}
}
输出
java
增加了观察者:喜羊羊
灰太狼:我要搞事情了
喜羊羊收到通知:灰太狼要搞事情了