2011-10-03 119 views
1

在扭曲的应用程序中,我有一系列通过Observable模式进行交互的资源控制器/管理器类。一般来说,大多数观察者都会订阅特定的频道(例如“foo.bar.entity2”),但在某些情况下,我想知道特定频道中的所有事件(例如“foo。*”)我写了类似以下内容:支持多通道订户的Python可观察实现

from collections import defaultdict 

    class SimplePubSub(object): 

     def __init__(self): 
      self.subjects = defaultdict(list) 


     def subscribe(self, subject, callbackstr): 
      """ 
       for brevity, callbackstr would be a valid Python function or bound method but here is just a string 
      """ 
      self.subjects[subject].append(callbackstr) 

     def fire(self, subject): 
      """ 
       Again for brevity, fire would have *args, **kwargs or some other additional message arguments but not here    
      """ 

      if subject in self.subjects: 
       print "Firing callback %s" % subject 
       for callback in self.subjects[subject]: 
        print "callback %s" % callback 



    pubSub = SimplePubSub() 
    pubSub.subscribe('foo.bar', "foo.bar1") 
    pubSub.subscribe('foo.foo', "foo.foo1") 

    pubSub.subscribe('foo.ich.tier1', "foo.ich.tier3_1") 
    pubSub.subscribe('foo.ich.tier2', "foo.ich.tier2_1") 
    pubSub.subscribe('foo.ich.tier3', "foo.ich.tier2_1") 

    #Find everything that starts with foo 
    #say foo.bar is fired 
    firedSubject = "foo.bar" 
    pubSub.fire(firedSubject) 
    #outputs 
    #>>Firing callback foo.bar 
    #>>callback foo.bar1 

    #but let's say I want to add a callback for everything undr foo.ich 

    class GlobalPubSub(SimplePubSub): 

     def __init__(self): 
      self.globals = defaultdict(list) 
      super(GlobalPubSub, self).__init__() 


     def subscribe(self, subject, callback): 
      if subject.find("*") > -1: 
       #assumes global suscriptions would be like subject.foo.* and we want to catch all subject.foo's 
       self.globals[subject[:-2]].append(callback) 
      else: 
       super(GlobalPubSub, self).subscribe(subject, callback) 

     def fire(self, subject): 
      super(GlobalPubSub, self).fire(subject) 
      if self.globals: 
       for key in self.globals.iterkeys(): 
        if subject.startswith(key): 
         for callback in self.globals[key]: 
          print "global callback says", callback 

    print "Now with global subscriptions" 
    print 
    pubSub = GlobalPubSub() 
    pubSub.subscribe('foo.bar', "foo.bar1") 
    pubSub.subscribe('foo.foo', "foo.foo1") 

    pubSub.subscribe('foo.ich.tier1', "foo.ich.tier3_1") 
    pubSub.subscribe('foo.ich.tier2', "foo.ich.tier2_1") 
    pubSub.subscribe('foo.ich.tier3', "foo.ich.tier2_1") 
    pubSub.subscribe("foo.ich.*", "All the ichs, all the time!") 

    #Find everything that starts with foo.ich 
    firedSubject = "foo.ich.tier2" 
    pubSub.fire(firedSubject) 
    #outputs 
    #>>Firing callback foo.bar 
    #>>callback foo.bar1 
    #>>Now with global subscriptions 
    # 
    #>>Firing callback foo.ich.tier2 
    #>>callback foo.ich.tier2_1 
    #>>global callback says All the ichs, all the time! 

这样就好,没有诉诸某种奇特的构造(例如尝试)?我正在寻求一种肯定,即我正处于正确的轨道上,或者是一个纯粹的Python(没有外部库或服务)的全球订阅处理程序的更好的替代建议。

回答

1

这看起来像你在正确的轨道上给我。我正在使用PyPubSub和一个wxPython应用程序,然后最终实现了我自己的“更简单”的版本,它的根本看起来和你在这里完成的非常相似,除了你有更多的花里胡哨的东西当你填写你的要求时,你可能会最终执行。

给出的答案here也很像你所做的一样。

answer进入有些不同的方法的例子。

PyPubSub外还有多个现有的库,如pydispatchblinker,可能值得您参考或参考。