PureMVC是一个轻量级MVC框架,对Model,View和Controller进一步解耦,使框架更容易扩展。PureMVC最初是用Adobe Flex中的ActionScript 3写的,后来移植到其它语言,现在支持:
Model, View和Controller之间的通讯并没有使用平台相关的UI事件机制,而使用了观察者模式。其中:
PureMVC提供了一个Facade类封装了对Model,View和Controller了的访问。Facade也负责Model,view和Contoller的初始化以及Proxy,Mediator和Command的注册。
Controller.py
model中实现计算,完成后发出更新UI的通知:
- ActionScript 2
- ActionScript 3
- C ++
- C #
- ColdFusion
- Dart
- Haxe
- Java
- JavaScript
- Objective C
- Perl
- PHP
- Python
- Ruby
- 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)
其它资料:
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