使用Publish/Subscribe 设计模式达到对象间数据同步

** 使用 ** ** Publish/Subscribe ** ** 设计模式达到对象间数据同步 ** ** **

应用程序经常需要更改和交换数据,必须传送这些更改后数据以达到对象的同步,尤其在多窗口用户界面应用程序中更要求这种数据的同步协调,在这一类应用程序中, 潜在的数据更新信息一定要反映到所有被包含的子窗体中。

例如一个人员信息管理的应用程序。一次可以打开多个包含一个人名字的窗口,如果你在其中一个窗口中修改并报存了这个人的名字,你将期望对名字改变应立即显示在其它全部窗体内。可以通过使用 Publish/Subscribe 设计模式来完成这种功能。这种设计模式是 Observer 模式(见图一)的一种变体。 Observer 模式在 Design Patterns, Elements of Reusable Object Oriented Software 书中有很详细的描述,在 Observer 模式中,一个对象( Observer 观察者)被注册到另一对象(主体 Subject ),用于监听事件。观察者( Observer ) 暗中地反映 (主体 Subject )的变化。


图一

** Publish/Subscribe ** ** 模式 ** (参见图二),在主体( Subject )和观察者( Observer )之间增加了一层间隔。 这个层移除了在观察者( Observer )和主体( Subject )之间的捆绑并且在这两之间建立一种松耦合的关系。 ** Event Channel ** 可以被描述成一个数据中心。


图二

Publisher ( 就是在观察者( Observer )模式中的主体( Subject ) ) 向这个 ** Event Channel ** . 发布事件。 ** Event Channel ** 的责任就是向所有的 ** Subscribers ** (就是在观察者( Observer )模式中的观察者( Observer ))散布事件。一个应用程序可以包含一个或多个 ** Event Channel ** ** , ** 所以,要向每个感兴趣的 ** Subscribers ** 来散布不同的事件。此外,在观察者( Observer )模式中事件仅仅来自特殊的来源,在 ** Publish/Subscribe ** ** 模式 ** 中任何注意 ** Event Channel ** 的对象都可以发布事件。 ** **

这个构造移除了观察者( Observer ) and 主体( Subject )之间的依赖。结果是你可以为你的应用程序增加更多的通用设计,此外,通过要求在 ** Publisher ** 和 ** Subscriber ** 之间的没有直接的关系,它大大增加你的应用程序的可维护性。

** 使用 ** ** Publish/Subscribe ** ** 模式 ** ** **

通过一个简单的例子来学习 ** Publish/Subscribe ** ** 模式 ** 是如何实现的。 EventApp. EventApp 是一个拥有一个 MDI 窗体和很多子窗体的应用环境。 ( 下载本文代码 ).

在你的程序中,你将需要创造一系列的基类来实现 ** Publish/Subscribe ** ** 模式 ** 。 在工程里的其他类都从这些基类派生而来(见图三)。 EventApp 应用程序有如下 3 个基类:


图三

  • ** clsEventChannel ** ---------------------- 为构建 ** event channels ** 的一个抽象类。
  • ** clsEvent ** -------------------------- 为构建事件的类型使用的一个抽象类。 它暴露了 4 个属性:
    • _ Name _ : 事件的名字
    • _ Value _ : 事件的价值
    • _ ExtraData _ : 被关联那些事件的其它数据
    • _ Origin _ : 可选择的参考鉴定事件的 ** publisher **
  • ** frmSubscriber ** – 用于创建窗口、接收事件的一个抽象 Windows Form

为了使一应用工作,你需要建立从那些基类继承的几个具体的类。 在这个例子当中,这些类是:

  • ** clsDataEvents ** - 从 clsEventChannel 类继承的一个具体的类。 在应用程序中,将它作为 ** event channel ** 来使用,它被用来向那些潜在的数据模型散布更新的信息。
  • ** clsDataEvent ** - 从 clsEvent 类继承并且用来创建事件,呈现潜在数据的更新的一个具体的类。 ( 要创建一个继承窗体,你可以在解决方案资源管理器中选择 " 添加 (Add)-> 添加继承的窗体 (Inherited Windows Form)" 的快捷菜单 。
  • ** frmList ** – 派生自 frmSubscriber 类的一个具体的类。它是 MDI 窗体的一个子窗体,用于显示数据列表。在这个例子中,这个窗体通过硬编码 用一个 Listview 控件显示了 10 条数据。

** EventApp ** ** 如何工作 **

当 EventApp 被启动时, frmMain( MDI 父窗体 ) 创造一个数据 ** event channel ** 实例 -----clsDataEvents :

Private Sub frmMain_Load(ByVal sender As Object, _


    ByVal e As System.EventArgs) Handles MyBase.Load


  mobjDataEventChannel = New clsDataEvents()


  Me.IsMdiContainer = True


  Me.Text = "Publish/Subscribe Event Sample"


  Me.WindowState = FormWindowState.Maximized


End Sub


       当MDI窗体被运行时,你可以在菜单中选择"File->New List"来创建一个frmList类的实例。


Private Sub MenuItem2_Click(ByVal sender As _


  System.Object, ByVal e As System.EventArgs) _


  Handles MenuItem2.Click


  Dim objNewForm As frmList


 


  objNewForm = New frmList()


  mobjDataEventChannel.AttachSubscriber(objNewForm)


  objNewForm.MdiParent = Me


  objNewForm.Show()


End Sub


当创建了子窗体以后,它将被注册到 **event channel** **,** 在注册过程期间, **event channel** 将要初始化 **subscriber** **。**


Public Overridable Sub Initialize(ByVal Token As _


  String, ByVal EventChannel As clsEventChannel)


  mstrToken = Token


  mobjEventChannel = EventChannel


End Sub
Published At
Categories with Web编程
Tagged with
comments powered by Disqus