利用观察者模式来对程序模块进行解耦

这段时间在对我们项目的代码进行重构,发现我们以往开发软件的时候耦合度非常高, 最严重的是很难对软件进行扩展和删减,现在对软件进行扩展的功能成本非常大

比如我们有一个模块a,当到打一定的时间,或者说条件后,需要调用它:

function()

{

function_a1()

function_a2()

function_a3()

}

这个时候软件还好,但是随着时间的增加,你需要加入b,c,d,e的功能,代码将会非常长,而且如果有时候我们需要阉割一些功能,或者说,我们需要增加一些功能,但是这个功能只是在某个客户所需求的,于是我们开始利用宏定义或者if语句配合配置文件来,达到所谓的扩展和删减功能,这样久了后,软件的主干部分是这样的:

function()

{

read_config()

if(need_a)

{

function_a1()

function_a2()

function_a3()

}

if(need_b)

{

function_b1()

function_b2()

.....

}

......

}

这样扩展下去后,你将会有两个问题:

配置文件膨胀

代码文件膨胀

在一个项目里面,不可能只有function这么简单的函数会用到其他的模块,可能你app init的时候,app destroy的时候,都需要因引用到其他模块,于是,这个问题会非常严重,而且在对一些客户进行定制开发的时候,他们也都需要在适当的时候调用对应的代码,于是不管在app init,app destroy或者其他地方,你总能看到一大堆的if语句,有时候我们要修改一个客户的功能,我们要先从几百个文件里面查找代码,然后在一个一个文件去修改

现在我们的一个配置文件有40+个配置项目,经常有时候出问题都不知道是哪个模块出问题,也不知道配置文件要怎么搞,一个cpp里面有6000+行代码,几乎include了整个系统的头文件,而且这个cpp里面实际上有3000+行都是针对单一客户的,也就是说,我们发一个版本给一个客户,实际上他也要了其他针对几十个客户的定制的模块

代码膨胀和配置文件膨胀是我们在维护上遇见的最大的问题

这样在团队开发的过程中,我们经常会遇见一个问题就是两个人都需要同时修改到function,如果一不小心,容易引起冲突,然后代码被覆盖掉,小乌龟在合并上做的不是很好,经常会提示冲突,需要手动解决,smartsvn在自动合并上就做得很好

耦合度太高也是我们团代配合时候经常会出现的问题

总之,这种开发模式下,我们的软件已经越来越复杂,维护越来越困难,从去年开始我开始思考如何做到更好的模块化,今年开始着手

就是引入了一个事件机制,当系统达到一定的条件后,将会去通知你,当然是前提你要告诉他,这个就是观察者模式,也可以说是sub/pub模式

比如像上面的function函数,我们模块a和模块b需要他调用,那么我们可以定义个虚基类,然后像function的管理类注册,到时间自动调用

如下:

class IModuleEvent

{

public:

virtual void OnEvent() = 0;

};

class EvtMgr

{

void RegisterEvt(IModuleEvent *evt)

{

m_EvtList.push_back(evt);

}

}

function()

{

for_each(EvtMgr.m_EvtList)

}

上面的是程序的核心部分,下面则是模块a

ModuleA:public IModuleEvent

{

ModuleA()

{

EvtMgr.RegisterEvt(this);

}

};

这样

  1. function不知道module a的存在,module a随时可以向EvtMgr注册事件,也可以随之滚蛋走人,就一句代码的事情,很容易扩展和删减
  2. module a的代码就肯定在模块,不会像之前那样散落在几十个地方,也不会造成代码冲突

基本就这样了,在对一个新的客户进行软件定制的时候,我开始对使用这套系统,虽然还没全部完成,但是到目前为止,我们已经可以很好的对新项目进行扩展和卸载,新的客户软件就是一个lib库,如果需要,那么我们让程序link我们的lib库就可以了

顺便说下,因为是使用lib库的原因,再者程序的核心部分并不知道有什么模块加入到这个软件里面,编译器不会主动去链接模块的lib,所以需要修改vs的强制符号引用,强制链接,后续可以通过改成dll来达到动态加载的目的

后续:

上面的程序使用了继承的方式,是不是觉得很麻烦,特别是在一个系统中,有几十个事件很正常,那岂不是要连续定义十多个class或者接口

其实现在已经有function和bind来取代虚函数了,推荐

http://blog.csdn.net/solstice/article/details/3066268

vs2010也自带了这个

再后续:

后续引入boost的signals2的库

时间: 2024-10-17 14:55:27

利用观察者模式来对程序模块进行解耦的相关文章

【java规则引擎】规则引擎RuleBase中利用观察者模式

(1)当RuleBase中有规则添加或删除,利用观察者模式实现,一旦有变动,规则引擎其他组件也做出相应的改变.(2)学习思想:当一个应用中涉及多个组件,为了实现易扩展,解耦思想.可以利用观察者模式实现.基于易变动的数据结构中加入监听者,监听者依据被监听者的变动动作,定义自己的动作.在监听者内部通知其他组件做出相应改变.实现面向对象的思想.组建之间实现了解藕. 一:被监听数据,也就是规则网络RuleBase的接口定义 1 package com.nonbankcard.commons.doorls

ExtJS要利用观察者模式 去实现自定义的事件

1 // 要利用观察者模式 去实现自定义的事件 2 3 4 //1:由于浏览器他自己能定义内置的事件(click/blur...) 5 // 我们也应该有一个类似于浏览器这样的类,这个类 自己去内部定义一些事件(自定义事件) 6 var Observable = function(){ 7 //承装自己所定义的事件类型的 8 this.events = ['start','stop']; 9 //我们应该设计一种数据类型,这种数据类型就可以去维护自定义事件类型 和 和相关绑定函数的关系,结构如下

多媒体之本地音乐的播放(利用观察者模式传值)及播放中控件的变化

在RootViewController的m文件里: 1 #import "RootViewController.h" 2 #import "ListViewController.h" 3 @interface RootViewController () 4 5 @end 6 7 @implementation RootViewController 8 9 - (void)viewDidLoad { 10 [super viewDidLoad]; 11 // Do a

c#设计模式(3)—— 利用观察者模式模拟推送消息

1.观察者模式概念 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己的行为. 观察者模式实现了表示层和数据逻辑层的分离,并定义了稳定的更新消息传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层,即观察者. 观察者模式在被观察者和观察者之间建立了一个抽象的耦合,被观察者并不知道任何一个具体的观察者,只是保存着抽象观察者的列表,每个具体观察者都符合一个抽象观察者的接口. 2.业务场景 模拟

Python实现简易HTTP服务器与MINI WEB框架(利用WSGI实现服务器与框架解耦)

本文描述如果简单实现自定义Web服务器与自定义简易框架,并且不断进行版本迭代,从而清晰的展现服务器与Web框架之间是如何结合.如何配合工作的.以及WSGI是什么. 一.选取一个自定义的服务器版本 参照 https://www.cnblogs.com/leokale-zz/p/11957768.html 中的各种服务器实现版本,我们选择比较简单的多进程版本作为演示版本. 代码如下: import socket import re import multiprocessing def handle_

Head First设计模式——观察者模式

前言: 这篇文章我们以Head First设计模式中讲解的气象站为例,通过它的案列进行学分析和编码(C#)测试,并归纳总结出观察者模式. 1.气象监测案列,错误示范实现 一个气象站,分别有三个装置:温度感应装置,湿度感应装置,气压感应装置.WeathData对象跟踪气象站数据,WeathData有MeasurmentsChanged()方法,当感应装置数据变化后就会调用MeasurmentsChanged对使用改数据的用户进行数据更新.目前需求是要三个布告板,分别是目前气象数据状况布告板(Cur

Spring中如何使用工厂模式实现程序解耦?

目录 1. 啥是耦合.解耦? 2. jdbc程序进行解耦 3.传统dao.service.controller的程序耦合性 4.使用工厂模式实现解耦 5.工厂模式改进 6.结语 @ 1. 啥是耦合.解耦? 既然是程序解耦,那我们必须要先知道啥是耦合,耦合简单来说就是程序的依赖关系,而依赖关系则主要包括 1. 类之间的依赖 2. 方法间的依赖 比如下面这段代码: public class A{ public int i; } public class B{ public void put(A a)

观察者模式实际应用:监听线程,意外退出线程后自动重启

摘要: 观察者模式,定义对象之间的一种一对多的依赖关系,当对象的状态发生改变时,所有依赖于它的对象都得到通知并且被自动更新.观察者模式在JDK中有现成的实现,java.util.Obserable. 首先说下需求:通过ftp上传约定格式的文件到服务器指定目录下,应用程序能实时监控该目录下文件变化,如果上传的文件格式符合要求,将将按照每一行读取解析再写入到数据库,解析完之后再将文件改名.(这个是原先已经实现了的功能,请看我的一篇文章java利用WatchService实时监控某个目录下的文件变化并

First Head 设计模式之观察者模式(Observer Pattern)

前言: 这一节开始学习观察者模式,开始讲之前会先像第一节那样通过一个应用场景来引入该模式.具体场景为:气象站提供了一个WeatherData对象,该对象可以追踪获取天气的温度.气压.湿度信息,WeatherData对象会随即更新三个布告板的显示:目前状况(温度.湿度.气压).气象统计和天气预报. 1.    基本需求:利用WeatherData对象获取数据.并更新三个布告板:目前状况.气象统计和天气预报 WeatherData类图如下: 说明: GetTemperature().GetHumid