目录
一、观察者模式解决了哪些问题:
二、体检的小栗子
三、什么是观察者模式
四、代码实现
一、观察者模式解决了哪些问题:
- 对象之间的一对多依赖关系应该在不使对象紧密耦合的情况下定义。
- 应该确保当一个对象改变状态时,自动更新无限数量的依赖对象。
- 一个对象可以通知无限数量的其他对象应该是可能的。
二、体检的小栗子
举一个生活中常见的小栗子。你想要了解自己的身体状况。
方案一:
想要了解自己眼睛,健康状况,去A医院,挂一个眼科进行检查
想要了解自己血糖,健康状况,去B医院,挂一个内科进行检查
想要了解自己肝功能状态,,去C医院,挂一个号进行检查。
方案二:做一个体检项目
做一个体检项目,项目里包含身高、体重、视力、血糖、肝功能等一系列检查。
如果我还想检查更多的项目,可能在体检套餐里加入特定的体检项目。
观察者模式:
体检(类)-检查(方法)
写一个体检接口,里面有检查方法。然后多个实现类:
体重类,需要实现体检接口的检查方法
身高类,需要实现体检接口的检查方法。
目的就是把所有的类,在类型上统一,都归属于体检类,这样就可以组成一个体检集合,然后遍历每个元素的检查方法
--------------------------------------------------------------------------------------------------------------------------
三、什么是观察者模式
主要解决:当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
关键代码:在抽象类里有一个 ArrayList 存放观察者们。
四、代码实现
需要进行体检的人类Person
package ObserverDemo;
import lombok.Data;
@Data
public class Person {
private String name;
private int height;
private int weight;
private int vision; // 视力
private String lung;// 肺部
private String blood; // 血液
}
体检接口HealthCheckupIObserver,有检查身体的方法
package ObserverDemo;
public interface HealthCheckupIObserver<T> {
void check(T t);
}
体检医院内,视力科室(Eye类)实现体检接口,来检查视力
package ObserverDemo;
public class Eye implements HealthCheckupIObserver<Person>{
@Override
public void check(Person person) {
System.out.println("进行视力检查");
}
}
体检医院内,内科室实现体检接口,来检查肺部
package ObserverDemo;
public class InternalMedicine implements HealthCheckupIObserver<Person>{
@Override
public void check(Person person) {
System.out.println("内科进行肺部检查");
}
}
体检医院内,外科科室实现体检接口,来检查身高
package ObserverDemo;
public class Surgery implements HealthCheckupIObserver<Person>{
@Override
public void check(Person person) {
System.out.println("外科进行身高检查");
}
}
体检单ObserverManager
将各种体检项目,加入到这个体检单里。也可以将体检单里的某一体检项目剔除。
package ObserverDemo;
import com.google.common.collect.Lists;
import java.util.List;
public class ObserverManager {
// 各种检查项目,组成一个体检单/list
private List<HealthCheckupIObserver> observers;
// 构造器,私有,不能被new
private ObserverManager(){
observers = Lists.newArrayList(
new InternalMedicine(),// 将 内科检查,加入到体检单
new Eye(), // 将眼科检查,加入到体检单
new Surgery() // 将外科检查,加入到体检单
);
}
// ClassHolder属于静态内部类,在加载类Demo03的时候,只会加载内部类ClassHolder,
// 但是不会把内部类的属性加载出来
private static class ClassHolder{
// 这里执行类加载,是jvm来执行类加载,它一定是单例的,不存在线程安全问题
// 这里不是调用,是类加载,是成员变量
private static final ObserverManager holder =new ObserverManager();
}
public static ObserverManager of(){//第一次调用getInstance()的时候赋值
return ClassHolder.holder;
}
public void check(Person person){
for (HealthCheckupIObserver observer:observers){
observer.check(person);
}
}
}
小明同学,使用体检单进行体检。
package ObserverDemo;
public class APP {
public static void main(String[] args) {
Person person = new Person();
ObserverManager.of().check(person);
}
}
感觉观察者的核心就是:
定义一个观察者接口,具体执行逻辑的类来实现它。就是为了能够将这几个实现类,组合成一个集合。然后调用遍历每个元素的方法。
在这个例子里,观察者的核心就是:
将各个检查项目,组装成了一个体检单。(体检单里可以增加或者剔除某个体检项目)
UML类图
项目结构: