昨天一个同学在MSN上问我一些问题,他正在用DELPHI做一个东西,类似于QQ这样的,即对不同的IP发来的UDP包信息,用不同的窗口显示。其类图大致如下:
可以看出,这是一个很明显的表现与逻辑混合的设计:其中MainForm除了作为主窗体以外,还要负责创建ChatForm,并维护ChatForms列表,并且当收到UDP包时,还要负责将其分发到相应的ChatForm。结果只能是出现一个巨大无比的MainForm,在其中包罗万有,最后常常会造成难以维护的下场。
这是从RAD开始编程的人的通常做法,同时也是RAD工具被人垢病的一个主要方面。
所以我给他提了一个建议,如下图:
在其中插入一个中间类,用于把MainForm中创建和维护ChatForms的功能剥离出来。至于分发UDP消息的功能,暂时可以继续放在MainForm里,由TChatFormManager提供一个根据源IP查询ChatForm的方法,MainForm通过调用此方法取得相应的ChatForm,并将UDP消息交由此ChatForm处理。
其实这就是一种消除“坏味道”的重构,其做法便是所谓的“Extract Class”。
因为他这个东西我也没看到,不知道他具体要做成什么样,所以只能给一个这样的简单意见。在实际的开发中,情况应该会复杂一些,比如有可能需要把UDP的分发放到一个单独的类中处理,或者可能有不同种类的ChatForm,则需要有一个Factory Method来处理创建工作……等等。
随便说说,仅供参考。^O^
最近在翻譯一篇小文章,也談到類似層的這種實現方式,不難,但體現一種很好的架構思想,到時翻完,再請猛禽指正!
指正可不敢当,我也就是一点体会而已。
Manager类这种,我现在见到最好的就是与月共舞在CnWizard里面的WizardMgr这个。他真的是下了功夫,简单又实用。猛Q也倾向于这种类型啊。
仍然来看看,虽然仍看不懂,哈哈
偶以为,分离的最终目的都是为了重用或者升级,同时使系统更易于理解,因此,采用组件方式构架此系统,或许更方便一些。如果仅在Delphi中的分离,实际上对于软件结构来说,是没有多大意义的,即便在Delphi中重用这些东西,也是没有什么意义的。也就是说,重用,要彻底。偶以为几个接口外加几个Bridge类,或许会更好,简单的设计大致类似于:IForm: 基础接口IMainUI:IForm负责管理用户界面的显示逻辑IUIHandler:负责处理UI的事件和应用逻辑,用于任何IForm,负责跟处理逻辑打交道。IChatForm:IForm:对话窗口,任何类型的对话窗口(信息,文件传送,声音,媒体传送等),均可从此派生。IMessageHandler: 信息处理器,诸如UDP,TCP/IP的Handler均可从此派生。Class MessageQueue: 信息队列
另外关于Patterns:1.基于组件的架构,本身都采用了Factory的patterns,作为默认实现,还应该有一个factory.2.基于UI与Logic分离的结构,大都可参看Facade,微软的大多数Demo,多采用此pattern.诸如Duwamish, Stock之类的。3.对于较为复杂的信息窗口的构造,可参看Builder之类的模式。4.偶认为,再加一个消息的Observer会不会更好?5. 解决问题是主要的,用不用patterns在其次。
对于风兄前一个评论,我不能同意。重构最重要的原则是小步,虽然你那个建议看上去是一个很美的设计,但是改动太大。其次我对他的应用没有具体了解的情况下,我不会建议他作这样的改动,设计没有好与坏之分,只有合适与不合适的区别。三,你这个设计等于放弃了VCL提供的好处,无形中增加了自己的工作量,没有必要。Facade和Observer是好东东,不过在他那个简单的应用中,暂时还没有必要搞得这么复杂。XP的原则是:只做必要的工作,一旦不能满足需要,我们就重构。^O^很同意你这一句:>解决问题是主要的,用不用patterns在其次。用Patterns的目的是为了解决问题,而不能是为了用Patterns而用Patterns。