观察者模式
观察者模式属于行为型模式,又叫发布订阅模式
定义:
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新
模式类图
角色:
- 被观察者:Subject定义一个被观察者必须实现职责,包括动态增加,删除,通知观察者
- 观察者:Observer接受到观察者修改消息,执行自身逻辑
- 具体观察者:ConctreteSubject继承Subject,拥有自己的业务逻辑,具有被观察者基本功能,对某些事件进行通知
- 具体的观察者:ConcreteObserver具体观察者,在接受到被观察者变更消息后,进行各自业务处理
优点
-
观察者和被观察者之间是抽象耦合,容易拓展
-
通过触发机制可以创建成一种链式触发机制,形成多级触发
缺点
-
执行效率
当通知观察者是顺序执行时,需要考虑整个观察者列表的数量,对整个通知事件执行效率的影响,可以考虑使用异步通知,同时尽量避免多级触发事件 -
循环依赖
当观察者和被观察之间形成循环依赖,会导致循环调用,比如A改变通知B,B改变通知C,C改变通知A,注意避免循环依赖的发生
被观察者接口
Subjectable 定义被观察者基本功能
public interface Subjectable {
/**
* 增加观察者
*/
void addObserver(Observerable observer);
/**
* 移除观察者
*/
void removeObserver(Observerable observer);
/**
* 通知观察者
*/
void notifyObserver(Object object);
}
被观察者抽象类
AbstractSubject被观察者类的公共父类,实现了被观察者基本功能的实现,使用Vector为观察者列表
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
@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;
}
}
观察者接口
public interface Observerable {
/**
* 被观察者变化触发事件
*/
void update(Object object);
}
具体观察者
SmsObserver 接收到被观察者密码变更,发送短信提醒
public class SmsObserver implements Observerable {
@Override
public void update(Object object) {
if(null == object){
return;
}
System.out.println("短信观察者");
System.out.println("短信发送提醒:密码更改为:"+object.toString());
}
}
EmailObserver 接收到被观察者密码变更,发送邮件提醒
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
参考:设计模式之禅:https://www.kancloud.cn/sstd521/design/193589