设计模式之观察者模式
-
使用场景:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
-
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
-
如何解决:使用面向对象技术,可以将这种依赖关系弱化。
-
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
-
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
举例:客户状态发生变更,客户下多个商户状态也要发生变更,商户状态发生变更,该商户下所有的账户状态也需要改变。
1.Subject 对象
/**
* @author ppeng
* @date 2020/9/26 15:58
* @description
*/
public class Subject {
private List<Observer> observerList = new ArrayList<>(10);
private String state;
public String getState(){
return this.state;
}
public void setState(String state){
this.state = state;
updateState();
}
public void register(Observer observer){
observerList.add(observer);
}
private void updateState(){
for (Observer observer : observerList) {
observer.updateState();
}
}
}
2.观察者对象
/**
* @author ppeng
* @date 2020/9/26 15:47
* @description
*/
public abstract class Observer {
protected Subject subject;
/**
* 更新状态
* @return
*/
abstract boolean updateState();
}
3.客户变更对象
public class CusStateService extends Observer {
public CusStateService(Subject subject) {
this.subject = subject;
subject.register(this);
}
@Override
public boolean updateState() {
System.out.println("更新客户状态:" + this.subject.getState());
return true;
}
}
4.商户状态变更对象
public class MerStateService extends Observer {
public MerStateService(Subject subject) {
this.subject = subject;
subject.register(this);
}
@Override
public boolean updateState() {
System.out.println("更新商户状态:" + this.subject.getState());
return true;
}
}
5.账户状态变更对象
public class AccountStateService extends Observer {
public AccountStateService(Subject subject) {
this.subject = subject;
subject.register(this);
}
@Override
public boolean updateState() {
System.out.println("更新账户状态:" + this.subject.getState());
return true;
}
}
6.测试类
public class Test {
public static void main(String[] args) {
Subject subject = new Subject();
new CusStateService(subject);
new MerStateService(subject);
new AccountStateService(subject);
subject.setState("注销");
System.out.println("---------------------------");
subject.setState("冻结");
}
}
7.控制台输出
Connected to the target VM, address: '127.0.0.1:6661', transport: 'socket'
更新客户状态:注销
更新商户状态:注销
更新账户状态:注销
---------------------------
更新客户状态:冻结
更新商户状态:冻结
更新账户状态:冻结
Disconnected from the target VM, address: '127.0.0.1:6661', transport: 'socket'
8.类图