2016-01-22 52 views
2

假设我们有一个MainView和另外两个视图。如果其他两个视图更新她的数据,他们应该能够通知MainView绘制数据。我不知道如何连接并通知(与Event.PLOT_DATASubControllerMainController使用MVC + Observer模式组织不同的控制器

下面是一个例子:

class Event(object): 
    PLOT_DATA = 1 
    UPDATE_VIEW = 2 

class MainModel(object): 
    def __init__(self): 
     self.x_data = [] 
     self.y_data = [] 

class Model2(object): 
    def __init__(self): 
     self.x_data = [] 
     self.y_data = [] 

    def __repr__(self): 
     return "<x_data=%s, y_data=%s>" % (self.x_data, self.y_data) 

    def __str__(self): 
     return "%s %s" % (self.x_data, self.y_data) 

class Controller(object): 
    def __init__(self): 
     self.model = None 
     self.views = [] 

    def get_data(self): 
     return self.model 

    def register(self, view): 
     self.views.append(view) 

    def unregister(self, view): 
     if view in self.views: 
      self.views.remove(view) 

    def notify(self, event): 
     for view in self.views: 
      view.update(event) 

class MainController(Controller): 
    def __init__(self): 
     Controller.__init__(self) 
     self.model = MainModel() 

    def change_model(self, x_data, y_data): 
     self.model.x_data = x_data 
     self.model.y_data = y_data 
     self.notify(Event.PLOT_DATA) 

class SubController(Controller): 
    def __init__(self): 
     Controller.__init__(self) 
     self.model = Model2() 

    def change_model(self, x_data, y_data): 
     self.model.x_data = x_data 
     self.model.y_data = y_data 
     self.notify(Event.UPDATE_VIEW) 

class MainView(object): 
    def __init__(self, controller): 
     self.controller = controller 
     self.controller.register(self) 
     self.sub_controller = SubController() 
     self.view1 = View1(self.sub_controller) 
     self.view2 = View2(self.sub_controller) 
     # some operations on view1 and view2 
     self.view1.funny_stuff() 
     self.view2.funny_stuff() 

    def plot_data(self, data): 
     print "Data of MainView: %s" % data 

    def update(self, event): 
     if event == Event.PlOT_DATA: 
      self.data = self.controller.model 
      self.plot_data(self.data) 

class View1(object): 
    def __init__(self, controller): 
     self.controller = controller 
     self.controller.register(self) 
     self.print_data() 

    def print_data(self): 
     print "View 1 data=%s" % self.controller.get_data() 

    def funny_stuff(self): 
     print "Change data on View 1" 
     self.controller.change_model([0, 1, 2], [0, 1, 2]) 

    def update(self, event): 
     if event == Event.UPDATE_VIEW: 
      print "Update View 1" 
      self.data = self.controller.model 
      self.print_data() 

class View2(object): 
    def __init__(self, controller): 
     self.controller = controller 
     self.controller.register(self) 
     self.print_data() 

    def print_data(self): 
     print "View 2 data=%s" % self.controller.get_data() 

    def funny_stuff(self): 
     print "Change data on View 2" 
     self.controller.change_model([3, 2, 1], [3, 2, 1]) 

    def update(self, event): 
     if event == Event.UPDATE_VIEW: 
      print "Update View 2" 
      self.data = self.controller.model 
      self.print_data() 

main_controller = MainController() 
main_view = MainView(main_controller) 

回答

0

的soulution是使用ControllerService其中连接两个控制器。 ControllerService存储origintarget控制器,并具有类似redirect的功能。该功能可以将事件发送到控制器。这里是一个例子:

class Controller(): 
    def __init__(self): 
     self.model = None 
     self.views = [] 

    def get_data(self): 
     return self.model 

    def register(self, view): 
     self.views.append(view) 

    def unregister(self, view): 
     if view in self.views: 
      self.views.remove(view) 

    def notify(self, event): 
     for view in self.views: 
      view.update(event) 

class Event(object): 
    UPDATE_VIEW = 1 
    PLOT_DATA = 2 
    FINISH_UPDATE = 3 

class MainModel(object): 
    def __init__(self): 
     self.x_data = [] 
     self.y_data = [] 

    def __repr__(self): 
     return "<x_data=%s, y_data=%s>" % (self.x_data, self.y_data) 

    def __str__(self): 
     return "%s %s" % (self.x_data, self.y_data) 

class Model2(object): 
    def __init__(self): 
     self.x_data = [] 
     self.y_data = [] 

    def __repr__(self): 
     return "<x_data=%s, y_data=%s>" % (self.x_data, self.y_data) 

    def __str__(self): 
     return "%s %s" % (self.x_data, self.y_data) 

class ControllerService(object): 
    def __init__(self): 
     self.origin = None 
     self.target = None 

    def add_origin(self, origin): 
     self.origin = origin 

    def add_target(self, target): 
     self.target = target 

    def redirect(self, event): 
     if self.target: 
      self.target.notify(event) 
     else: 
      print "No target controller found." 

class MainController(Controller): 
    def __init__(self, controller_service): 
     Controller.__init__(self) 
     self.model = MainModel() 

     self.controller_service = controller_service 
     self.controller_service.add_target(self) 

    def get_controller_service(self): 
     return self.controller_service 

    def change_model(self, x_data, y_data): 
     self.model.x_data = x_data 
     self.model.y_data = y_data 
     self.notify(Event.PLOT_DATA) 

class SubController(Controller): 
    def __init__(self, controller_service): 
     Controller.__init__(self) 
     self.model = Model2() 

     self.controller_service = controller_service 
     self.controller_service.add_origin(self) 

    def change_model(self, x_data, y_data): 
     self.model.x_data = x_data 
     self.model.y_data = y_data 
     self.notify(Event.UPDATE_VIEW) 

    def finish_updating(self): 
     self.controller_service.redirect(Event.UPDATE_VIEW) 

class MainView(object): 
    def __init__(self, controller): 
     self.controller = controller 
     self.controller.register(self) 
     self.controller_service = self.controller.get_controller_service() 
     self.sub_controller = SubController(self.controller_service) 
     self.view1 = View1(self.sub_controller) 
     self.view2 = View2(self.sub_controller) 
     # some operations on view1 and view2 
     self.view1.funny_stuff() 
     self.view2.funny_stuff() 
     self.view2.finish_updating() 

    def update(self, event): 
     if event == Event.UPDATE_VIEW: 
      model = self.controller_service.origin.model 
      self.controller.change_model(model.x_data, model.y_data) 
     if event == Event.PLOT_DATA: 
      print "Plot: %s" % self.controller.model 

class View1(object): 
    def __init__(self, controller): 
     self.controller = controller 
     self.controller.register(self) 
     self.print_data() 

    def print_data(self): 
     print "View 1 data=%s" % self.controller.get_data() 

    def funny_stuff(self): 
     print "Change data on View 1" 
     self.controller.change_model([0, 1, 2], [0, 1, 2]) 

    def update(self, event): 
     if event == Event.UPDATE_VIEW: 
      print "Update View 1" 
      self.print_data() 

class View2(object): 
    def __init__(self, controller): 
     self.controller = controller 
     self.controller.register(self) 
     self.print_data() 

    def print_data(self): 
     print "View 2 data=%s" % self.controller.get_data() 

    def funny_stuff(self): 
     print "Change data on View 2" 
     self.controller.change_model([3, 2, 1], [3, 2, 1]) 

    def finish_updating(self): 
     print "All views are updated" 
     self.controller.finish_updating() 

    def update(self, event): 
     if event == Event.UPDATE_VIEW: 
      print "Update View 2" 
      self.print_data() 

controller_service = ControllerService() 
main_controller = MainController(controller_service) 
main_view = MainView(main_controller)