2011-05-24 51 views
0

我正在處理一些代碼來組織我們的事件定義/類別映射。我們的目標是能夠定義「事件名稱」以及關聯類別,它幾乎是一個靜態過程。我們想要的是人們使用常量,而不是到處都是一堆字符串。我們還需要某個地方來驗證事件/類別,以及按照類別進行事件查找等操作,反之亦然。Python事件類別映射設計

class EventMapping(object) 
    def __init__(self, name, categories): 
     self.name = name 
     self.categories= categories 
     EventRegistry.register(self) 

    def __eq__(self, obj): 
     if(isinstance(obj, str)): 
      return obj==self.name 
     if(isinstance(obj, EventMapping)): 
      return obj.name ==self.name 
       and obj.categories==self.categories 
     return False 

    def __repr__(self): 
     return self.name 

class Event(): 
    class MyCompontent(): 
     ComponentEvent = EventMapping("ComponentEvent", None) 
     ComponentEventWCategory = EventMapping("ComponentEvent" 
      , [Category.MyComponent.Useful]) 
    class Data(): 
     Created =EventMapping("Created", [Category.Data.All, Category.Data.Count] 
     Updated= EventMapping("Updated", [Category.Data.All] 
     Deleted= EventMapping("Deleted", [Category.Data.All, Category.Data.Count] 

class Category(): 
    class MyComponent(): 
     Useful = "Useful" 
    class Data(): 
     All= "All" 
     Count= "Count" 

class EventRegistry(): 
    @staticmethod 
    def register(eventMapping): 
     eventName= eventMapping.name 
     #store locally... 

    @staticmethod 
    def events(category): 
     #retreive events by category 

    @staticmethod 
    def category(event_name): 
     #retreive categories by event name 

有一對夫婦的事情,我不喜歡:

  1. 在EventRegistry I類存儲在一個事件字典鍵存儲它們兩次,一次是名字,值列表的類別。第二種是按類別名稱和事件列表鍵入的相反類別字典。有沒有更好的方法來實現這一目標?我基本上需要一個簡單的方法來查看名稱或類別。

  2. 我應該只創建兩個註冊表嗎?一個用於事件分類一個?

  3. 當涉及到使用事件,我們不喜歡它:

    ​​ self.subscribe(Category.MyComponent.Useful)

,我們使用註冊表來驗證事件存在,以及傳遞消息。有沒有更簡單的方法來實現類似命名空間的包?

只是尋找更好的方法來做一些反饋,或者遵循一個模式。我已經四處搜尋,找不到任何東西。即使你知道一些模塊,我可以看看,並有一個更好的方式來做一個更好的感覺,生病也很高興看到這一點。

回答

1

爲什麼不去something more pythonic

from collections import defaultdict 


_linked = defaultdict(set) 


class Linkable(object): 

    def link(self, *others): 
     _linked[self].update(others) 
     for each in others: 
      _linked[each].add(self) 

    def unlink(self, *others): 
     _linked[self].difference_update(others) 
     for each in others: 
      _linked[each].discard(self) 

    def links(self): 
     return set(_linked[self]) 


class NameHierarchy(object): 

    def __init__(self, name, parent=None): 
     self.name = name 
     self.parent = parent or self 
     self.path = parent.path + [self] if parent else [self] 

    def __str__(self): 
     return '.'.join(each.name for each in self.path) 

    def add(self, name): 
     if name not in self.__dict__: 
      setattr(self, name, self.__class__(name, self)) 


class LinkedNameHierarchy(Linkable, NameHierarchy): 
    pass 


Category = LinkedNameHierarchy('Category') 

Category.add('MyComponent') 
Category.MyComponent.add('Useful') 

Category.add('Data') 
Category.Data.add('All') 
Category.Data.add('Count') 

Event = LinkedNameHierarchy('Event') 

Event.add('MyComponent') 
Event.MyComponent.add('ComponentEvent') 
Event.MyComponent.add('ComponentEventWCategory') 

Event.MyComponent.ComponentEventWCategory.link(Category.MyComponent.Useful) 

Event.add('Data') 
Event.Data.add('Created') 
Event.Data.add('Updated') 
Event.Data.add('Deleted') 

Event.Data.Created.link(Category.Data.All, Category.Data.Count) 
Event.Data.Updated.link(Category.Data.All) 
Event.Data.Deleted.link(Category.Data.All, Category.Data.Count) 


def show_links(): 
    print 
    print '----8<--------8<--------8<--------8<--------8<--------8<----' 
    for k, v in sorted(_linked.iteritems(), key=lambda x:str(x[0])): 
     print 
     print k 
     for each in sorted(v, key=str): 
      print '  ', each 

show_links() 

Event.Data.Created.unlink(Category.Data.Count) 

show_links() 

有循環引用,通常會導致內存泄漏。在這種情況下,它可以,因爲這些對象大概活着,只要proram運行。

+0

我喜歡定義事件的設計,我只是想確保它仍然適合我們正在努力完成的事情。我們必須做的一件重要事情是能夠通過事件或類別進行檢索,並且我認爲我仍然會被卡住。但至少這次我不需要管理關係。我正在考慮添加一個標誌來指示「類型」事件vs類別。然後我可以將它們存儲在一個集合中。 – Nix 2011-05-25 13:22:22

+0

我做了另一個版本,可以在[這裏]獲得(http://paste.pocoo.org/show/395925)。它包含更多的魔力,但也更靈活。請注意,NameHierarchy現在是一個類裝飾器函數,它返回裝飾類的一個實例。 – pillmuncher 2011-05-26 23:59:23

+0

我最終做了這樣的事情,唯一不喜歡的就是無法使用「自動完成」。我想知道是否有隻是定義'Event.MyComponent.ComponentEvent'的pythonic方法,它會自動註冊'Event.MyComponent.add('ComponentEvent')'。我的解決方案,我不喜歡.add後,我只是輸入完整的事件名稱,它使自動完成來顯示事件。 – Nix 2011-06-08 18:45:24