观察者模式
观察者模式属于行为型模式
定义:
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新
模式类图
角色:
- 被观察者:
Subject
定义一个被观察者必须实现职责,包括动态增加,删除,通知观察者 - 观察者:
Observer
接受到观察者修改消息,执行自身逻辑 - 具体观察者:
ConctreteSubject
继承Subject
,拥有自己的业务逻辑,具有被观察者基本功能,对某些事件进行通知 - 具体的观察者:
ConcreteObserver
具体观察者,在接受到被观察者变更消息后,进行各自业务处理
优点
- 观察者和被观察者之间是抽象耦合,容易拓展
- 通过触发机制可以创建成一种链式触发机制,形成多级触发
缺点
执行效率
当通知观察者是顺序执行时,需要考虑整个观察者列表的数量,对整个通知事件执行效率的影响,可以考虑使用异步通知,同时尽量避免多级触发事件
循环依赖
当观察者和被观察之间形成循环依赖,会导致循环调用,比如A改变通知B,B改变通知C,C改变通知A,注意避免循环依赖的发生
模式代码实现
以用户修改密码为例,当用户密码改变后,使用短信和邮件对用户进行消息提醒
源码地址:https://github.com/mingyuHub/design-patterns
被观察者接口
Subjectable
定义被观察者基本功能
/**
* @author: chenmingyu
* @date: 2019/3/15 13:44
* @description: 被观察者接口
*/
public interface Subjectable {
/**
* 增加观察者
*/
void addObserver(Observerable observer);
/**
* 移除观察者
*/
void removeObserver(Observerable observer);
/**
* 通知观察者
*/
void notifyObserver(Object object);
}
被观察者抽象类
AbstractSubject
被观察者类的公共父类,实现了被观察者基本功能的实现,使用Vector
为观察者列表
/**
* @author: chenmingyu
* @date: 2019/3/15 11:24
* @description: 被观察者抽象类
*/
public abstract class AbstractSubject implements Subjectable{
/**
* 观察者列表
*/
private Vector<Observerable> observers = new Vector();
@Override
public void addObserver(Observerable observer){
observers.add(observer);
}
@Override
public void removeObserver(Observerable observer){
observers.add(observer);
}
@Override
public void notifyObserver(Object object){
observers.forEach(observer->{
observer.update(object);
});
}
}
被观察者类
UserInfo
实现AbstractSubject
/**
* @author: chenmingyu
* @date: 2019/3/15 13:50
* @description: 被观察者
*/
@Data
public class UserInfo extends AbstractSubject{
/**
* 昵称
*/
private String nickName;
/**
* 密码
*/
private String password;
/**
* 修改密码
* @param password
*/
public void updatePassword(String password){
this.password = password;
this.notifyObserver(password);
}
public UserInfo(String nickName, String password) {
this.nickName = nickName;
this.password = password;
}
}
观察者接口
/**
* @author: chenmingyu
* @date: 2019/3/15 13:40
* @description: 观察者
*/
public interface Observerable {
/**
* 被观察者变化触发事件
*/
void update(Object object);
}
具体观察者
SmsObserver
接收到被观察者密码变更,发送短信提醒
/**
* @author: chenmingyu
* @date: 2019/3/15 13:56
* @description: 短信观察者
*/
public class SmsObserver implements Observerable {
@Override
public void update(Object object) {
if(null == object){
return;
}
System.out.println("短信观察者");
System.out.println("短信发送提醒:密码更改为:"+object.toString());
}
}
EmailObserver
接收到被观察者密码变更,发送邮件提醒
/**
* @author: chenmingyu
* @date: 2019/3/15 13:54
* @description: 邮件观察者
*/
public class EmailObserver implements Observerable{
@Override
public void update(Object object) {
if(null == object){
return;
}
System.out.println("邮件观察者");
System.out.println("邮件发送提醒:密码更改为:"+object.toString());
}
}
验证
public static void main(String[] args) {
UserInfo userInfo = new UserInfo("麻辣香锅","malaxiangguo");
SmsObserver smsObserver = new SmsObserver();
EmailObserver emailObserver = new EmailObserver();
userInfo.addObserver(smsObserver);
userInfo.addObserver(emailObserver);
userInfo.updatePassword("mlxg");
}
输出
短信观察者
短信发送提醒:密码更改为:mlxg
邮件观察者
邮件发送提醒:密码更改为:mlxg
SmsObserver
和EmailObserver
观察到UserInfo
用户麻辣香锅更改密码为mlxg