原理

  • 思想:当对象间存在一对多关系时,可以使用观察者模式。当一个对象被修改时,会自动通知依赖它的对象。
  • 如何使用:一个对象(被观察者)的状态发生改变,所有的依赖对象(观察者)都将得到通知,进行广播通知。
  • 优点:观察者和被观察者是抽象耦合的;需要建立一套触发机制。
  • 注意点: Java中内置了观察者模式的支持类。

基于SpringBoot的案例

思路:创建多个Listener(观察者),一个事件(被观察者)。当事件发布时候,触发Listener。示例代码如下: //被观察者 @Component public class User { public void say(){ System.out.println(“Hello AOP~”); } }

//观察者
@Component
public class UserListener {
    @EventListener
    @Async
    public void listenUser0(User user) throws InterruptedException {
        System.out.println("观察者0,观察到了User:"+user);
        //测试异步观察
        Thread.sleep(1000);
    }

    @EventListener
    @Async
    public void listenUser1(User user){
        System.out.println("观察者1,观察到了User:"+user);
    }
}

//测试
@SpringBootApplication
@PropertySource(value = {"classpath:db.properties"})
@EnableAsync
public class SpringDemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args);
        User user = new User();
        context.publishEvent(user);
    }
}

结果如下:

基于springboot的观察者示例

基于Java的案例

思路:通过继承Observable类创建TestSubject类,设定当数据改变时,先后调用setChanged()和notifyObservers()方法来进行广播。通过实现Observer接口来创建两个观察者ObserverOne和ObserverTwo两个观察者来订阅TestSubject。示例代码如下:

//被观察者
public class TestSubject extends Observable {
    private Integer id;
    private String msg;

    public TestSubject(Integer id, String msg){
        this.id=id;
        this.msg=msg;
    }

    public void setData(Integer id, String msg){
        this.id=id;
        this.msg=msg;
        //调用setChanged(),否则调动同步方法不会被执行
        this.setChanged();
        //同步
        this.notifyObservers(this);
    }
}

//以下是两个观察者
public class ObserverOne implements Observer {

    public ObserverOne(TestSubject subject){
        //调阅主题
        subject.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("我是观察者0,被观察者(类型)为:"+o.getClass().getName());
        System.out.println("同步传递参数为:"+arg);
    }
}

public class ObserverTwo implements Observer {

    public ObserverTwo(TestSubject subject){
        subject.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("我是观察者1,被观察者(类型)为:"+o.getClass().getName());
        System.out.println("同步传递参数为:"+arg);
    }
}

//测试
public class BasicTest {

    public static void main(String[] args){
        TestSubject originalMsg = new TestSubject(1, "originalMsg");
        new ObserverOne(originalMsg);
        new ObserverTwo(originalMsg);
        originalMsg.setData(2,"updatedMsg");
    }
}

结果如下:

java自带的观察者

结语

观察者模式即订阅思想,被订阅方需要广播更新,订阅方需要对更新做出处理。