作为一名在工业软件领域摸爬滚打多年的老程序员,我发现很多开发者对观察者模式的理解往往停留在理论层面。最近在为某大型制造企业开发设备监控系统时,我深刻体会到了观察者模式在实际项目中的强大威力。想象一下:当生产线上的温度传感器数值异常时,监控大屏、报警系统、数据库记录模块都能第一时间收到通知并作出响应,这种松耦合的设计让系统既稳定又易于扩展。
今天就来分享一套完整的工业监控系统实现方案,帮你彻底掌握观察者模式的实战应用。
在没有使用观察者模式之前,我们通常会这样写代码:
C#// ❌ 传统的紧耦合写法
public class Sensor
{
private MonitorPanel panel;
private AlarmSystem alarmSystem;
private DatabaseLogger logger;
public void UpdateValue(double newValue)
{
this.value = newValue;
// 直接调用各个模块
panel.UpdateDisplay(this.name, newValue);
if(newValue > maxValue)
alarmSystem.TriggerAlarm(this.name, newValue);
logger.LogData(this.name, newValue);
}
}
这种写法存在明显问题:
观察者模式通过定义一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题状态发生变化时,所有观察者都会收到通知。

C#// 观察者接口
public interface IObserver
{
void Update(string sensorName, double value, DateTime timestamp, string status);
}
// 主题接口
public interface ISubject
{
void Attach(IObserver observer);
void Detach(IObserver observer);
void Notify();
}
设计要点:
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppObserverIndustrialMonitoringSystem
{
// <summary>
/// 工业传感器类 - 主题实现
/// </summary>
public class Sensor : ISubject
{
private List<IObserver> _observers;
private string _name;
private double _value;
private DateTime _timestamp;
private string _unit;
private double _minValue;
private double _maxValue;
private string _location;
public string Name => _name;
public double Value => _value;
public DateTime Timestamp => _timestamp;
public string Unit => _unit;
public double MinValue => _minValue;
public double MaxValue => _maxValue;
public string Location => _location;
public Sensor(string name, string unit, double minValue, double maxValue, string location)
{
_observers = new List<IObserver>();
_name = name;
_unit = unit;
_minValue = minValue;
_maxValue = maxValue;
_location = location;
_value = (minValue + maxValue) / 2;
_timestamp = DateTime.Now;
}
public void Attach(IObserver observer)
{
if (!_observers.Contains(observer))
_observers.Add(observer);
}
public void Detach(IObserver observer)
{
_observers.Remove(observer);
}
public void Notify()
{
string status = GetStatus();
foreach (IObserver observer in _observers)
{
observer.Update(_name, _value, _timestamp, status);
}
}
public void SetValue(double value)
{
_value = Math.Round(value, 2);
_timestamp = DateTime.Now;
Notify();
}
private string GetStatus()
{
if (_value < _minValue) return "偏低";
if (_value > _maxValue) return "偏高";
return "正常";
}
public bool IsNormal()
{
return _value >= _minValue && _value <= _maxValue;
}
}
}
💡 实战技巧:
Contains检查避免重复添加观察者SetValue方法中自动调用Notify(),确保数据一致性C#public partial class FrmMainMonitor : Form, IObserver
{
private List<Sensor> _sensors;
private DataTable _sensorDataTable;
private Random _random = new Random();
public void Update(string sensorName, double value, DateTime timestamp, string status)
{
// 跨线程调用处理
if (InvokeRequired)
{
Invoke(new Action<string, double, DateTime, string>(Update),
sensorName, value, timestamp, status);
return;
}
UpdateSensorDisplay(sensorName, value, timestamp, status);
}
private void UpdateSensorDisplay(string sensorName, double value, DateTime timestamp, string status)
{
// 更新DataGridView数据
foreach (DataRow row in _sensorDataTable.Rows)
{
if (row["传感器名称"].ToString() == sensorName)
{
row["当前值"] = value.ToString("F2");
row["状态"] = status;
row["更新时间"] = timestamp.ToString("HH:mm:ss");
break;
}
}
// 根据状态设置行颜色
UpdateRowColor(sensorName, status);
// 异常时添加报警
if (status != "正常")
{
AddAlert(sensorName, value, status, timestamp);
}
}
}
⚠️ 关键注意点:
InvokeRequired处理跨线程UI更新C#private void SimulateSensorValue(Sensor sensor)
{
double range = sensor.MaxValue - sensor.MinValue;
double baseValue = sensor.MinValue + range * 0.5; // 基准值
double variation = range * 0.3 * (_random.NextDouble() - 0.5); // ±15%波动
double newValue = baseValue + variation;
// 15%概率产生异常值(模拟真实故障场景)
if (_random.NextDouble() < 0.15)
{
if (_random.NextDouble() < 0.5)
newValue = sensor.MinValue - range * 0.1; // 低于正常值
else
newValue = sensor.MaxValue + range * 0.1; // 高于正常值
}
sensor.SetValue(Math.Max(0, newValue));
}

C#// 状态颜色定义
Color normalColor = Color.FromArgb(46, 204, 113); // 绿色-正常
Color warningColor = Color.FromArgb(241, 196, 15); // 黄色-警告
Color errorColor = Color.FromArgb(231, 76, 60); // 红色-异常
Color primaryColor = Color.FromArgb(52, 152, 219); // 蓝色-主题
使用TableLayoutPanel实现自适应布局,确保在不同分辨率下都有良好的显示效果:
C#// 主布局:60% 数据区 + 20% 控制区 + 20% 报警区
tlpMain.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 60F));
tlpMain.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
tlpMain.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
C#// 轻松添加新的监控模块
var temperatureSensor = new Sensor("锅炉温度", "°C", 80, 120, "A区锅炉房");
// 一个传感器可以有多个观察者
temperatureSensor.Attach(mainMonitorForm); // 主界面
temperatureSensor.Attach(alarmSystem); // 报警系统
temperatureSensor.Attach(dataLogger); // 数据记录
temperatureSensor.Attach(cloudUploader); // 云端上传
C#public class SmartSensor : Sensor
{
private double _lastNotifyValue;
private DateTime _lastNotifyTime;
public override void Notify()
{
// 只在值变化超过阈值或时间间隔足够时才通知
if (Math.Abs(_value - _lastNotifyValue) > 0.1 ||
DateTime.Now.Subtract(_lastNotifyTime).TotalSeconds > 5)
{
base.Notify();
_lastNotifyValue = _value;
_lastNotifyTime = DateTime.Now;
}
}
}
C#public void Update(object data)
{
if (InvokeRequired)
{
Invoke(new Action<object>(Update), data);
return;
}
// 实际更新逻辑
}
C#public void Attach(IObserver observer)
{
if (!_observers.Contains(observer))
_observers.Add(observer);
}
C#public void Notify()
{
var observersCopy = new List<IObserver>(_observers);
foreach (var observer in observersCopy)
{
try
{
observer.Update(/* 参数 */);
}
catch (Exception ex)
{
// 记录日志,但不影响其他观察者
Console.WriteLine($"Observer update failed: {ex.Message}");
}
}
}
通过这个完整的工业监控系统案例,我们掌握了观察者模式的三个核心要点:
观察者模式不仅仅是一个设计模式,更是一种编程思维。在实际项目中,它能帮我们构建更加灵活、可维护的系统架构。
你在项目中遇到过哪些需要用观察者模式解决的场景? 或者在实现过程中碰到了什么技术难题?欢迎在评论区分享你的经验,让我们一起交流学习!
如果这篇文章对你有帮助,请转发给更多需要的同行,让更多C#开发者受益!
相关信息
通过网盘分享的文件:AppObserverIndustrialMonitoringSystem.zip 链接: https://pan.baidu.com/s/11TNypox6TPHTQFm2PLkJ9Q?pwd=88rp 提取码: 88rp --来自百度网盘超级会员v9的分享
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!