观察者模式 (Observer Pattern)

观察者模式是一种行为设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象状态发生变化时,它会通知所有观察者对象,使它们能够自动更新自己。

特别适合需要实现事件处理、数据绑定和响应式编程的场景。在Android开发中,LiveData、RxJava和EventBus等都是观察者模式的实现或变体。

核心概念
· Subject (主题): 被观察的对象,维护观察者列表并提供添加、删除和通知观察者的方法
· Observer (观察者): 定义更新接口,用于在主题状态改变时接收通知
· ConcreteSubject (具体主题): 存储状态,状态改变时向观察者发出通知
· ConcreteObserver (具体观察者): 实现观察者接口,保持与主题状态的一致性

Java 示例

// 观察者接口  
interface Observer {  
    void update(String message);  
}  
  
// 主题接口  
interface Subject {  
    void registerObserver(Observer o);  
    void removeObserver(Observer o);  
    void notifyObservers();  
}  
  
// 具体主题实现  
class ConcreteSubject implements Subject {  
    private List<Observer> observers = new ArrayList<>();  
    private String state;  
  
    public void setState(String state) {  
        this.state = state;  
        notifyObservers(); // 状态改变时通知所有观察者  
    }  
  
    @Override  
    public void registerObserver(Observer o) {  
        observers.add(o);  
    }  
  
    @Override  
    public void removeObserver(Observer o) {  
        observers.remove(o);  
    }  
  
    @Override  
    public void notifyObservers() {  
        for (Observer observer : observers) {  
            observer.update(state);  
        }  
    }  
}  
  
// 具体观察者实现  
class ConcreteObserver implements Observer {  
    private String name;  
      
    public ConcreteObserver(String name) {  
        this.name = name;  
    }  
      
    @Override  
    public void update(String message) {  
        System.out.println(name + " received: " + message);  
    }  
}  

LiveData 示例

class MyViewModel : ViewModel() {  
    private val _data = MutableLiveData<String>()  
    val data: LiveData<String> = _data  
      
    fun updateData(newData: String) {  
        _data.value = newData // 观察者会自动收到更新  
    }  
}  
  
class MyActivity : AppCompatActivity() {  
    private lateinit var viewModel: MyViewModel  
      
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
          
        viewModel = ViewModelProvider(this).get(MyViewModel::class.java)  
          
        // 观察LiveData的变化  
        viewModel.data.observe(this, Observer { newData ->  
            // UI自动更新  
            textView.text = newData  
        })  
          
        // 触发数据变化  
        button.setOnClickListener {  
            viewModel.updateData("Button clicked at ${System.currentTimeMillis()}")  
        }  
    }  
}  

优点:

  • 松耦合: 主题和观察者之间抽象耦合,主题不需要知道观察者的具体类
  • 支持广播通信: 主题变化时自动通知所有观察者
  • 符合开闭原则: 可以轻松添加新观察者而无需修改主题代码

缺点:

  • 意外更新: 观察者不知道彼此的存在,可能导致意外的更新
  • 性能问题: 如果观察者很多,通知所有观察者可能耗时

适用场景

  • 当一个对象的改变需要同时改变其他对象,而不知道具体有多少对象需要改变时
  • 当一个对象必须通知其他对象,但又希望这些对象是松散耦合的
  • 在Android开发中,用于实现数据与UI的自动同步

相关模式:
发布-订阅模式: 观察者模式的变体,使用主题和订阅者之间的中间件(消息队列)进一步解耦
中介者模式: 通过中介对象封装一系列对象之间的交互,减少对象间的直接依赖