|
|
|
|
from cppy.cp_util import *
|
|
|
|
|
'''
|
|
|
|
|
订阅者 = 注册者 = 观察者
|
|
|
|
|
|
|
|
|
|
注册回调的一个变体
|
|
|
|
|
要点是:中心化、统一化
|
|
|
|
|
|
|
|
|
|
为了简化消息订阅可能形成的复杂性,
|
|
|
|
|
提供一个中心消息管理器统一负责消息的订阅和回调
|
|
|
|
|
各个功能组件只是完成自己的功能,
|
|
|
|
|
在中心管理器上订阅消息挂到自己响应的处理函数上
|
|
|
|
|
|
|
|
|
|
总结,相比较的改变:
|
|
|
|
|
- 注册的时候,通过提供一个类型字段标识不同消息
|
|
|
|
|
- 其它实体不做注册和做回调,统一这两个功能到一个中心单元
|
|
|
|
|
|
|
|
|
|
这是一个示例性质的原型,具体分布式环境下需要调整
|
|
|
|
|
'''
|
|
|
|
|
from collections import defaultdict
|
|
|
|
|
#################################################
|
|
|
|
|
# Event Manager
|
|
|
|
|
#################################################
|
|
|
|
|
class EventManager:
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self._subs = defaultdict(list)
|
|
|
|
|
|
|
|
|
|
def subscribe(self, event_type, handler):
|
|
|
|
|
self._subs[event_type].append(handler)
|
|
|
|
|
|
|
|
|
|
def publish(self, event):
|
|
|
|
|
event_type = event[0]
|
|
|
|
|
for handle in self._subs.get(event_type, []):
|
|
|
|
|
handle(event)
|
|
|
|
|
|
|
|
|
|
#################################################
|
|
|
|
|
# Application Entities
|
|
|
|
|
#################################################
|
|
|
|
|
class DataStorage:
|
|
|
|
|
def __init__(self, event_manager):
|
|
|
|
|
self._event_manager = event_manager
|
|
|
|
|
self._event_manager.subscribe('load', self._load)
|
|
|
|
|
self._event_manager.subscribe('start', self.produce_words)
|
|
|
|
|
|
|
|
|
|
def _load(self, event):
|
|
|
|
|
self._data = extract_file_words( event[1] )
|
|
|
|
|
|
|
|
|
|
def produce_words(self, _):
|
|
|
|
|
for word in self._data:
|
|
|
|
|
self._event_manager.publish(('word', word ))
|
|
|
|
|
self._event_manager.publish(('eof', None))
|
|
|
|
|
|
|
|
|
|
class StopWordFilter:
|
|
|
|
|
def __init__(self, event_manager):
|
|
|
|
|
self._event_manager = event_manager
|
|
|
|
|
self._event_manager.subscribe('load', self.load_stop_words)
|
|
|
|
|
self._event_manager.subscribe('word', self.filter_word)
|
|
|
|
|
self._stop_words = set()
|
|
|
|
|
|
|
|
|
|
def load_stop_words(self, _ ):
|
|
|
|
|
self._stop_words = set( get_stopwords() )
|
|
|
|
|
|
|
|
|
|
def filter_word(self, event):
|
|
|
|
|
word = event[1]
|
|
|
|
|
if word not in self._stop_words:
|
|
|
|
|
self._event_manager.publish(('valid_word', word))
|
|
|
|
|
|
|
|
|
|
class WordFrequencyCounter:
|
|
|
|
|
def __init__(self, event_manager):
|
|
|
|
|
self._event_manager = event_manager
|
|
|
|
|
self._event_manager.subscribe('valid_word', self.count_word)
|
|
|
|
|
self._event_manager.subscribe('print', self.print_freqs)
|
|
|
|
|
self._word_freqs = {}
|
|
|
|
|
|
|
|
|
|
def count_word(self, event):
|
|
|
|
|
word = event[1]
|
|
|
|
|
self._word_freqs[word] = self._word_freqs.get(word, 0) + 1
|
|
|
|
|
|
|
|
|
|
def print_freqs(self, _ ):
|
|
|
|
|
print_word_freqs ( sort_dict (self._word_freqs) )
|
|
|
|
|
|
|
|
|
|
class WordFrequencyApp:
|
|
|
|
|
def __init__(self, event_manager):
|
|
|
|
|
self._event_manager = event_manager
|
|
|
|
|
self._event_manager.subscribe('run', self.start_application)
|
|
|
|
|
self._event_manager.subscribe('eof', self.stop_application)
|
|
|
|
|
|
|
|
|
|
def start_application(self, event):
|
|
|
|
|
path_to_file = event[1]
|
|
|
|
|
self._event_manager.publish(('load', path_to_file))
|
|
|
|
|
self._event_manager.publish(('start', ))
|
|
|
|
|
|
|
|
|
|
def stop_application(self, _ ):
|
|
|
|
|
self._event_manager.publish(('print', ))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
event_manager = EventManager()
|
|
|
|
|
DataStorage( event_manager )
|
|
|
|
|
StopWordFilter( event_manager )
|
|
|
|
|
WordFrequencyCounter( event_manager )
|
|
|
|
|
WordFrequencyApp( event_manager )
|
|
|
|
|
event_manager.publish(('run', testfilepath ))
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|