概述:
观察者模式通常由两个对象组成:观察者和被观察者。当被观察者状态发生改变时,它会通知所有的观察者对象,使他们能够及时做出响应,所以也被称作“发布-订阅模式”。
特点:
-
优点:
解耦且可以在程序运行时动态增加或删除观察者对象。开放封闭原则,如果要添加一个观察者只需要新增一个观察者对象就可以
-
缺点:
当动态创建一个观察者过多,没有被正确移除时会导致内存泄露的异常。
循环依赖问题(可使用弱实体、依赖注入容器解决)
组成:
抽象被观察者》具体被观察者》抽象观察者》具体观察者
应用场景:
-
生活:
1、粉丝(观察者)和博主(被观察者)。博主发布一条博客或者文章,然后通知给说所有粉丝。
2、共享单车(被观察者)和用户(观察者)。当有新的共享单车被租用时,系统会发送通知给用户。 -
程序:
1、当一个对象的状态发生改变时,需要通知多个对象作出响应。例如,软件更新前,会通知所有用户需要更新的时间
2、当很对对象同事对某一个主题感兴趣时,可以拆用观察者模式实现发布订阅模式。例如生产者发送消息到消息队列中,并通知所有订阅此队列的消费者进行消费。
UML图:
代码示例:
/**
* 被观察者抽象
*/
interface Subscribe {
void addObserve(Observer observer);
void removeObserve(Observer observer);
void notifyObserve(String name);
}
/**
* 观察者抽象
*/
interface Observer {
void shopping(String name);
}
/**
* 被观察者具体 商城
*/
class Mall implements Subscribe{
List<Observer> observers = new ArrayList<>();
@Override
public void addObserve(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserve(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObserve(String name){
observers.forEach(e->{
e.shopping(name);
});
}
}
/**
* 观察者具体
*/
class Client implements Observer{
String userName;
@Override
public void shopping(String name) {
System.out.println(userName + "抢购商品:" + name);
}
public Client(String userName) {
this.userName = userName;
}
}
@org.junit.Test
public void test(){
Client zhangShan = new Client("张三");
Client liSi = new Client("李四");
Client wangWu = new Client("王五");
Mall mall = new Mall();
mall.addObserve(zhangShan);
mall.addObserve(liSi);
mall.addObserve(wangWu);
mall.notifyObserve("波司登羽绒服");
}
结果:
张三抢购商品:波司登羽绒服
李四抢购商品:波司登羽绒服
王五抢购商品:波司登羽绒服