如何正确使用观察者模式?关于通知时机决策主体的技术问询
Great question—this is such a thoughtful observation about the Observer Pattern, and it gets to the heart of balancing responsibility and flexibility in design. Let’s break this down.
First: Why the Traditional Pattern Often Has the Subject Control the Trigger
In classic Observer Pattern implementations, the Subject holds the state and decides when to notify observers because it’s the source of truth for that state. This makes sense when all observers care about the same trigger condition, or when the Subject needs to optimize notifications (e.g., avoiding spamming observers with every tiny state change when only meaningful updates matter).
But as you’ve noticed, this couples the trigger logic (like the 95°C threshold) to the Subject, which becomes a problem when you want observers to have their own rules for reacting.
How to Shift Trigger Control to the Observer
Your intuition is spot-on: you can absolutely let observers decide when to act. The fix lies in adjusting the pattern to use a "pull" approach (or full-state push) instead of a conditional push. Here’s how to refactor your heater example:
Modified Heater (Subject)
Instead of checking the threshold inside the Subject, we’ll notify observers every time the temperature changes:
namespace Heater { public class Heater { // Subject private int temperature; public delegate void TemperatureChangedHandler(int para); public event TemperatureChangedHandler TemperatureChanged; public void BoilWater() { for (int i = 0; i <= 100; i++) { temperature = i; // Notify observers of EVERY temperature change TemperatureChanged?.Invoke(temperature); } } }
Modified Alarm (Observer)
Now the Alarm handles the threshold check itself:
public class Alarm { // Observer private int _threshold = 95; // Threshold lives in the Observer now! public void CheckTemperature(int currentTemp) { if (currentTemp > _threshold) { Console.WriteLine("ALARM: UP TO 95, NOW is {0}", currentTemp); } } } }
Usage
When wiring them up, subscribe the Alarm’s CheckTemperature method to the Heater’s TemperatureChanged event. Now, if you want to change the threshold (say to 90°C), you only modify the Alarm class—no touching the Heater at all.
When to Use Which Approach?
- Subject-controlled trigger: Use this when all observers need to react to the same condition, or when the Subject needs to throttle updates (e.g., only notify when state changes by more than 1°C to reduce noise).
- Observer-controlled trigger: Use this when observers have unique rules for reacting, or when you want to keep the Subject focused solely on managing state and notifications (not business logic for observer reactions).
Wrap-Up
The Observer Pattern doesn’t mandate that the Subject controls notification timing—it’s just a common starting point. By shifting the condition check to the observer, you get the flexibility you’re looking for while keeping the core decoupling benefit of the pattern intact.
内容的提问来源于stack exchange,提问作者user9010294

