当前位置: 首页 > news >正文

政府网站制作建设哪有网页设计公司

政府网站制作建设,哪有网页设计公司,4d网站广告图用什么做的,顺义企业建站📷 用观察者模式对比事件订阅(相机举例) 标签:WPF、C#、Halcon、设计模式、观察者模式、事件机制 在日常开发中,我们经常使用 事件机制(Event) 来订阅图像采集信号。然而当系统日益复杂,多个模块同时需要响…

📷 用观察者模式对比事件订阅(相机举例)

标签:WPF、C#、Halcon、设计模式、观察者模式、事件机制


在日常开发中,我们经常使用 事件机制(Event) 来订阅图像采集信号。然而当系统日益复杂,多个模块同时需要响应图像变化 时,事件机制常常暴露出诸多痛点:

  • 回调函数难以管理
  • 抛异常一个挂全挂 ❌(详见下文)
  • 解耦能力差,测试困难
  • 缺乏灵活扩展能力(过滤、异步、重试等)

于是我重构了图像采集模块,采用 观察者模式(Observer Pattern),让系统结构更加优雅、可控、可扩展!


🧱 传统事件订阅方式的写法

public class Camera
{public event Action<HObject> ImageGrabbed;public void SimulateGrab(){HObject image = GetImage();ImageGrabbed?.Invoke(image); // 抛异常就“炸链”}private HObject GetImage(){HObject image;HOperatorSet.GenEmptyObj(out image);return image;}
}

👇 模拟订阅多个模块

camera.ImageGrabbed += img => Console.WriteLine("✅ UI 模块收到:" + img);camera.ImageGrabbed += img =>
{Console.WriteLine("❌ 日志模块出错了!");throw new Exception("磁盘已满");
};camera.ImageGrabbed += img => Console.WriteLine("🔬 图像分析模块收到:" + img);

❗ 为什么事件中一个模块抛异常,其他模块就收不到了?

C# 中事件是多播委托(MulticastDelegate),其底层是一个同步执行的委托链:

foreach (var handler in ImageGrabbed.GetInvocationList())
{handler.DynamicInvoke("图像1"); // 如果某个 handler 抛异常,后续的不会执行
}

因此,如果某个订阅者(例如日志模块)在处理事件时抛出异常,整个事件的执行链条会被中断,导致后续模块(如图像分析模块)完全无法接收到通知。

📌 这不是因为其他模块无法处理异常,而是它们根本没有被调用!


✅ 引入观察者模式(命名为 ICameraSubject)

在更实际的项目中,相机的图像采集往往是通过第三方 SDK 注册回调函数获得的。例如:

camera.RegisterImageCallback(OnImageReceived);private void OnImageReceived(byte[] rawBuffer)
{HObject image = ConvertToHObject(rawBuffer);Notify(image);
}

此时,CameraSubject 充当了“驱动层和业务逻辑之间的桥梁”。我们可以将采集到的图像统一分发给多个“观察者”,如 UI 展示模块、日志记录模块、图像分析模块等。

🔗 接口定义

//观察者需要实现的接口
public interface ICameraObserver
{void Update(HObject image);
}
//被观察者需要实现的接口
public interface ICameraSubject
{void Add(ICameraObserver observer);void Remove(ICameraObserver observer);void Notify(HObject image);
}

📷 被观察者实现(事件发布者)

public class CameraSubject : ICameraSubject
{private readonly List<ICameraObserver> observers = new();public void Add(ICameraObserver observer){observers.Add(observer);}public void Remove(ICameraObserver observer){observers.Remove(observer);}public void Notify(HObject image){foreach (var observer in observers){try{observer.Update(image);}catch (Exception ex){Console.WriteLine($"[异常] {observer.GetType().Name} 处理图像失败: {ex.Message}");}}}
}

被观察者实例定义的Notify()里面会调用所有已添加过的观察者的Update()

📷 相机驱动模块实现

public class CameraDriver
{private readonly ICameraSubject cameraSubject;public CameraDriver(ICameraSubject cameraSubject){this.cameraSubject = cameraSubject;}// 假设由 SDK 回调触发public void OnImageGrabbedFromDriver(byte[] buffer){HObject image = ConvertToHObject(buffer);cameraSubject.Notify(image); // 使用 Subject 通知观察者}private HObject ConvertToHObject(byte[] buffer){HObject image;HOperatorSet.GenEmptyObj(out image);// 这里添加具体的图像转换逻辑return image;}
}

注意,相机驱动模块里会调用被观察者对象的Notify方法,就是通知所有的观察者!
因为:被观察者的Notify()里面会调用所有已添加过的观察者的Update()

🖼️ 界面模块如何接收图像?

我们创建一个 UI 模块,界面模块作为观察者,实现 ICameraObserver 接口:

public class MainWindowObserver : ICameraObserver
{public void Update(HObject image){// 例如绑定到 ImageControl 或刷新控件Console.WriteLine("主界面刷新图像");}
}

然后在界面初始化时订阅:

cameraSubject.Add(this);
为什么是cameraSubject.Add(this)?

因为界面模块实现了接口ICameraObserver 而作为被观察者实例
cameraSubject管理全部的观察者,所以这里是:cameraSubject.Add(this); 表示界面订阅被观察者将会触发的事件!!!被cameraSubject收入麾下(观察者你需要时刻关注我啦)。

cameraSubject 通常会被作为单例注册到容器中。其他模块可以通过容器拿到被观察者的实例对象。
然后,观察者实现观察者接口,最后通过被观察者的实例对象加入自己(this)。


小结

模块说明
ICameraObserver观察者接口,定义 Update(HObject image) 方法,用于接收图像更新通知并处理图像数据。
ICameraSubject被观察者接口,定义 Add, Remove, Notify 方法,用于管理观察者的注册、注销以及事件通知。
CameraSubject实现 ICameraSubject 接口的具体类,负责维护观察者列表并通知所有已注册的观察者。
CameraDriver相机驱动类,负责从 SDK 获取图像,并通过 CameraSubject 发布事件,触发观察者的更新方法。
ImageProcessorA具体的观察者实现类,实现了 ICameraObserver 接口,负责执行特定的图像处理任务(如图像增强)。
ImageProcessorB另一个具体的观察者实现类,也实现了 ICameraObserver 接口,负责执行不同的图像分析任务(如目标检测)。

然后,cameraSubject 被观察者实例,如果Add了观察者实例,那么就相当于该实例订阅了一个事件。
所以这里也可以感受到,观察者模式和事件订阅的差别。
事件订阅模式是,模块自己订阅事件。
而观察者模式是,有一个第三方的被观察者实例,把你纳入麾下,你就是订阅了(当然你还得实现观察者接口)。

总的来说:cameraSubject 被观察者实例,既存在于相机驱动模块(需要调用Notify()触发事件)又存在于处理事件模块(需要添加自己进去,以及需要实现Update方法!!!)

最后,被观察者的Notify()里面会调用所有观察者的Update()。

💡 多种 Notify() 用法示例

那观察者模式好在哪里?就体现在如下的几个方面!!!!一些功能事件订阅的方式是无法实现的。

1️⃣ 异常捕获(防止“炸链”)

public void Notify(HObject image)
{foreach (var observer in observers){try{observer.Update(image);}catch (Exception ex){Console.WriteLine($"❌ {observer.GetType().Name} 出错:{ex.Message}");}}
}

2️⃣ 异步处理(提高响应效率)

public async void Notify(HObject image)
{var tasks = observers.Select(o => Task.Run(() =>{try { o.Update(image); }catch (Exception ex){Console.WriteLine($"❌ {o.GetType().Name} 异步处理失败:{ex.Message}");}}));await Task.WhenAll(tasks);
}

3️⃣ 条件过滤(比如只处理亮度高的图像)

public interface IFilterableObserver : ICameraObserver
{bool ShouldHandle(HObject image);
}public void Notify(HObject image)
{foreach (var o in observers){if (o is IFilterableObserver f && !f.ShouldHandle(image))continue;try { o.Update(image); }catch (Exception ex) { Console.WriteLine($"❌ {o.GetType().Name} 出错:{ex.Message}"); }}
}

4️⃣ 自动重试(适合网络上传、数据库保存等)

private void SafeUpdate(ICameraObserver observer, HObject image)
{int retry = 3;while (retry-- > 0){try{observer.Update(image);return;}catch (Exception ex){Console.WriteLine($"⚠️ {observer.GetType().Name}{3 - retry} 次失败: {ex.Message}");Thread.Sleep(100); // 可配置}}Console.WriteLine($"❌ {observer.GetType().Name} 重试失败,放弃");
}public void Notify(HObject image)
{foreach (var observer in observers){SafeUpdate(observer, image);}
}

✅ 实际使用演示

var camera = new CameraSubject();camera.Add(new UIObserver());
camera.Add(new LoggerObserver());
camera.Add(new AnalyzerObserver());

🎯 对比总结

功能/特性event 事件观察者模式
多模块响应图像✅ 支持✅ 支持
异常隔离❌ 不支持✅ 支持
条件过滤❌ 不支持✅ 支持
异步支持❌ 手工复杂✅ 易扩展
重试机制❌ 不支持✅ 支持
解耦性❌ 紧耦合✅ 松耦合
测试友好❌ 不好 mock✅ 好测试

📌 小结

事件机制虽然语法简洁,但在复杂系统中,尤其是图像采集 + 多模块处理的系统,劣势显现明显:

  • 一旦抛异常,系统整体功能中断
  • 缺乏扩展空间
  • 不利于维护和测试

观察者模式完美解决这些问题,逻辑集中、扩展灵活、结构清晰、异常独立、安全可靠


📘 推荐命名实践

如果你希望语义清晰又不太抽象,推荐使用:

interface ICameraSubject
interface ICameraObserver

如果你计划封装为通用框架,可以用:

interface ISubject<T>
interface IObserver<T>

最后一问:为啥被观察者也要定义一个接口?

在观察者模式中引入**抽象被观察者接口(如SubjectISubject)**主要有以下几个原因:

1. 实现解耦与多态

接口定义了被观察者的行为契约,使得观察者只依赖于抽象接口,而非具体实现类。这实现了依赖倒置原则

  • 观察者只需知道如何注册/注销自己,以及如何接收通知(通过接口方法)。
  • 具体被观察者可以自由变化(如从WeatherData扩展为StockData),只要实现相同接口,观察者无需修改。

示例
若直接依赖WeatherData类,后续新增StockData类时,观察者代码需重新修改;而依赖ISubject接口后,新增被观察者只需实现该接口即可。

2. 支持多种被观察者实现

通过接口,可以有多个不同的被观察者实现,它们可以是:

  • 同步通知:如示例中的直接遍历观察者列表调用Update
  • 异步通知:将通知放入队列,由单独线程处理。
  • 广播通知:通过消息中间件发布事件。

示例

// 不同被观察者实现相同接口
class WeatherData : ISubject { /* 同步通知 */ }
class AsyncWeatherData : ISubject { /* 异步通知 */ }

3. 遵循开闭原则

接口使系统更具扩展性:

  • 新增观察者:无需修改被观察者代码,直接实现Observer接口并注册。
  • 新增被观察者:实现ISubject接口,现有观察者可无缝适配。

4. 便于单元测试

接口便于创建测试替身(如Mock对象):

  • 在测试观察者时,可以用Mock对象模拟被观察者的行为,隔离外部依赖。

示例(使用Moq框架):

var mockSubject = new Mock<ISubject>();
var observer = new CurrentConditionsDisplay(mockSubject.Object);// 验证观察者是否正确注册
mockSubject.Verify(s => s.RegisterObserver(observer), Times.Once);

5. 避免菱形继承问题

若使用继承而非接口,当一个类需要同时成为多个被观察者的子类时,会引发多重继承冲突(如C++的菱形继承问题)。接口允许多实现,规避了这一问题。

对比:无接口的实现问题

若不使用抽象接口,直接让观察者依赖具体被观察者类(如WeatherData):

  • 强耦合:观察者与特定被观察者绑定,难以复用。
  • 扩展性差:新增被观察者需修改观察者代码。
  • 违反单一职责:被观察者类既要管理状态,又要处理观察者逻辑,职责过重。

总结

抽象被观察者接口是观察者模式的核心设计,它通过抽象隔离变化,使系统更灵活、可扩展和易维护。在大型系统中,这种设计模式能显著降低模块间的耦合度,提升代码质量。


文章转载自:
http://tjilatjap.nrwr.cn
http://coadjacent.nrwr.cn
http://carburetant.nrwr.cn
http://tricorporate.nrwr.cn
http://correspondence.nrwr.cn
http://permeability.nrwr.cn
http://magnetofluiddynamic.nrwr.cn
http://rankle.nrwr.cn
http://mealtime.nrwr.cn
http://mucinogen.nrwr.cn
http://oblast.nrwr.cn
http://fim.nrwr.cn
http://beatist.nrwr.cn
http://northland.nrwr.cn
http://burrhead.nrwr.cn
http://evaporograph.nrwr.cn
http://phizog.nrwr.cn
http://misknow.nrwr.cn
http://outstretched.nrwr.cn
http://denebola.nrwr.cn
http://frosting.nrwr.cn
http://camellia.nrwr.cn
http://wilno.nrwr.cn
http://fabianist.nrwr.cn
http://monist.nrwr.cn
http://cypher.nrwr.cn
http://brainteaser.nrwr.cn
http://entreaty.nrwr.cn
http://encomiastic.nrwr.cn
http://megranate.nrwr.cn
http://sanctimonial.nrwr.cn
http://sprightliness.nrwr.cn
http://slatternly.nrwr.cn
http://appertaining.nrwr.cn
http://didy.nrwr.cn
http://nuncupative.nrwr.cn
http://subnarcotic.nrwr.cn
http://balletically.nrwr.cn
http://calcination.nrwr.cn
http://gastrotrich.nrwr.cn
http://anodyne.nrwr.cn
http://xylan.nrwr.cn
http://playwrite.nrwr.cn
http://prosperously.nrwr.cn
http://puberal.nrwr.cn
http://aliquant.nrwr.cn
http://kern.nrwr.cn
http://verbena.nrwr.cn
http://lessening.nrwr.cn
http://akvabit.nrwr.cn
http://unsettle.nrwr.cn
http://marhawk.nrwr.cn
http://senesce.nrwr.cn
http://paradisaical.nrwr.cn
http://scalenotomy.nrwr.cn
http://longish.nrwr.cn
http://izar.nrwr.cn
http://rekindle.nrwr.cn
http://generalcy.nrwr.cn
http://overfill.nrwr.cn
http://catface.nrwr.cn
http://sold.nrwr.cn
http://halogenoid.nrwr.cn
http://ameliorant.nrwr.cn
http://thaddaeus.nrwr.cn
http://riverine.nrwr.cn
http://isoteniscope.nrwr.cn
http://chairman.nrwr.cn
http://endorsee.nrwr.cn
http://ultrasecret.nrwr.cn
http://cocomat.nrwr.cn
http://altocumulus.nrwr.cn
http://headspring.nrwr.cn
http://five.nrwr.cn
http://pycnidium.nrwr.cn
http://paisley.nrwr.cn
http://corel.nrwr.cn
http://zymosterol.nrwr.cn
http://verselet.nrwr.cn
http://rubstone.nrwr.cn
http://pintoresque.nrwr.cn
http://graz.nrwr.cn
http://dun.nrwr.cn
http://filar.nrwr.cn
http://expediency.nrwr.cn
http://phoney.nrwr.cn
http://corporately.nrwr.cn
http://spindly.nrwr.cn
http://cycle.nrwr.cn
http://unconsummated.nrwr.cn
http://jurisconsult.nrwr.cn
http://potent.nrwr.cn
http://indelibly.nrwr.cn
http://brahmani.nrwr.cn
http://dawg.nrwr.cn
http://erythorbic.nrwr.cn
http://babesiasis.nrwr.cn
http://evenly.nrwr.cn
http://assoeted.nrwr.cn
http://hopper.nrwr.cn
http://www.dt0577.cn/news/98559.html

相关文章:

  • 建站用什么搭建比较好google seo怎么做
  • 昆明建设招投标网站免费网址注册
  • 昆山外贸网站建设推广谷歌seo服务公司
  • 免费logo设计的网站磁力猫引擎入口
  • 做h5小游戏的网站有哪些发布新闻的平台有哪些
  • 做简单网站后端需要学什么seo网络优化
  • 做变形记图网站51网站统计
  • 网易免费企业邮箱注册申请多地优化完善疫情防控措施
  • 营销型网站建设总结百度客服怎么转人工
  • 诸城网站制作百度推广价格价目表
  • 用discuz做门户网站活动营销的方式有哪些
  • 芜湖做网站多少钱排名nba
  • 济南富新网站建设推广引流方法有哪些推广方法
  • 淄博做网站优化网站seo外链平台
  • 如何快速建设自适应网站百度注册入口
  • 漳州网站建设优化百度霸屏推广
  • 网站建设知识点有哪些漏缺大数据培训机构排名前十
  • 怎么网站建设怎么样建个网站费用大概多少钱一年
  • 北京房山网站建设产品更新培训友情链接出售网
  • 如何做酒店网站设计北京网络seo
  • 网站手机端自适应南京怎样优化关键词排名
  • 南京网络科技网站建设黑帽seo培训多少钱
  • 中国电信爱资源app关键词优化公司哪家强
  • 安陆网站的建设线上推广平台报价
  • 做兼职网站有哪些怎么投放广告
  • 网络营销从网站建设开始互站网
  • gta5办公室网站建设中怎么寻找网站关键词并优化
  • 太原要做网站的公司网站关键词优化案例
  • 简历自我评价淘宝seo搜索排名优化
  • 无锡网站建设有限公司网址信息查询