PureMVC筆記

PureMVC是一個輕量級MVC框架,對Model,View和Controller進一步解耦,使框架更容易擴展。PureMVC最初是用Adobe Flex中的ActionScript 3寫的,後來移植到其它語言,現在支持:
  •  ActionScript 2
  •  ActionScript 3
  •  C ++
  •  C #
  •  ColdFusion
  •  Dart
  •  Haxe
  •  Java
  •  JavaScript
  •  Objective C
  •  Perl
  •  PHP
  •  Python
  •  Ruby
PureMVC中多了3種角色,它們分別和Model,  View和Controller緊密聯繫:
  • Model和Proxy: Model保存Proxy的引用,Proxy負責操作Model中都數據,使Model複用性更高
  • View和Mediator: View保存Mediator引用,Mediator操作視圖組件,處理UI事件
  • Controller和Command: Controller中保存了Command的映射,Command主要控制業務邏輯

Model, View和Controller之間的通訊並沒有使用平臺相關的UI事件機制,而使用了觀察者模式。其中:
  • Mediator可以發送和處理Notification
  • Proxy只能發送Notification
  • Notification也可以觸發Command

PureMVC提供了一個Facade類封裝了對Model,View和Controller了的訪問。Facade也負責Model,view和Contoller的初始化以及Proxy,Mediator和Command的註冊。

下面是一個PyQt4的demo,實現一個簡單的計算器:


Facade是個單例,在初始化方法中註冊兩個Command。StartUpCommand 註冊Proxy和Mediator,ButtonPressedCommand調用model的計算方法

main.py:

class AppFacade(Facade):
    
    START_UP = 'facade.start_up'
    INPUT = 'facade.input'
    
    @staticmethod
    def getInstance():
        return AppFacade()
    
    '''register command to controller'''
    def initializeFacade(self):
        super(AppFacade, self).initializeFacade()
        
        self.registerCommand(AppFacade.START_UP, controller.StartUpCommand)
        self.registerCommand(AppFacade.INPUT, controller.ButtonPressedCommand)

Controller.py

class ButtonPressedCommand(SimpleCommand):
    
    def execute(self, note):
        calcService = self.facade.retrieveProxy(model.CalcProxy.NAME)
        calcService.calc(note.getBody())
        
class StartUpCommand(SimpleCommand):
    
    def execute(self, note):
        appDialog = note.getBody()
        
        '''register mediator, connect app dialog with mediator'''
        self.facade.registerMediator(view.CalcMediator(appDialog ))

        '''register proxy'''
        self.facade.registerProxy(model.CalcProxy())

View中處理UI事件和發出Notification, 觸發Controller中對應的Command

view.py

class CalcMediator(Mediator):
    
    NAME = 'CalcMediator'
    
    def __init__(self, widget):
        super(CalcMediator, self).__init__(self.NAME,widget)
        
        QtCore.QObject.connect(self.viewComponent, QtCore.SIGNAL('buttonPressed'), self.buttonPressed)
    
    
    '''list of notification name, override'''
    def listNotificationInterests(self):
        return [
            model.CalcProxy.UPDATE_SCREEN
        ]
    
    '''handle notification'''
    def handleNotification(self, note):
        if (note.getName() ==  model.CalcProxy.UPDATE_SCREEN):
            self.viewComponent.screenLable.setText(note.getBody())
    
    '''slot'''
    def buttonPressed(self, text):
        screenValue = self.viewComponent.screenLable.text()
        
        if ('=' == text):
            self.sendNotification(main.AppFacade.INPUT, screenValue, None)
        else:
            if screenValue != '0':
                screenValue += text
            else:
                screenValue = text
            
            self.viewComponent.screenLable.setText(screenValue)
 

model中實現計算,完成後發出更新UI的通知:

model.py

class CalcProxy(Proxy):
    
    NAME = 'CalcProxy'
    
    UPDATE_SCREEN = 'model.update'
        
    def __init__(self, data = None):
        super(CalcProxy, self).__init__(self.NAME, data)
        
    def calc(self, string):
        
        string = str(string)
        
        '''int to flot'''
        if string.find('.') == -1 :
            string += '.'
        
        '''remove 0, in the end of result if it's integer, e.g: 15.0'''
        result = eval(string)
        if (result == int(result)):
            result = int(result)
        
        self.sendNotification(CalcProxy.UPDATE_SCREEN, str(result), None)

DEMO源碼


其它資料:

PureMVC:http://www.puremvc.org

實戰PureMVC:http://www.ibm.com/developerworks/cn/java/j-lo-puremvc/index.html

PyQt:http://www.riverbankcomputing.co.uk/software/pyqt/intro

Qt Calculator Example: http://doc.qt.nokia.com/4.7-snapshot/widgets-calculator.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章