简介
本文介绍的是MVC模式和如何在python中实现。
主题
MVC是用来分离关注点的。
Model负责管理程序的数据模型。View/Controller负责向外界提供与客户端数据交互的方法。
Model提供了供程序其他部分与它交互的API。View/Controller提供了一个外部界面(GUI/CLI/Web form/ high-level IPC/etc),使程序外的与之沟通。
Model不包含任何view/controller代码:没有gui 控件的类,没有布局,没有接收任何用户的输入。
MVC程序的本质上,就算没有View/Controll的代码,也应该是完整的,虽然操纵它变得困难。但是只要我们知道Model的API,这个程序将正常的操作数据。
Model不应该知道view/controller的任何东西, View/Controller允许知道Model的一部分(特别是,Model的API)。
why? 因为MVC是穿建一个明确的关注点分离。
例子
wxpython
#!/usr/bin/env python
import wx
# an observable calls callback functions when the data has changed
#o = Observable()
# def func(data):
# print "hello", data
# o.addCallback(func)
# o.set(1)
# --| "hello", 1
class Observable:
def __init__(self, initialValue=None):
self.data = initialValue
self.callbacks = {}
def addCallback(self, func):
self.callbacks[func] = 1
def delCallback(self, func):
del self.callback[func]
def _docallbacks(self):
for func in self.callbacks:
func(self.data)
def set(self, data):
self.data = data
self._docallbacks()
def get(self):
return self.data
def unset(self):
self.data = None
class Model:
def __init__(self):
self.myMoney = Observable(0)
def addMoney(self, value):
self.myMoney.set(self.myMoney.get() + value)
def removeMoney(self, value):
self.myMoney.set(self.myMoney.get() - value)
class View(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, title="Main View")
sizer = wx.BoxSizer(wx.VERTICAL)
text = wx.StaticText(self, label="My Money")
ctrl = wx.TextCtrl(self)
sizer.Add(text, 0, wx.EXPAND | wx.ALL)
sizer.Add(ctrl, 0, wx.EXPAND | wx.ALL)
ctrl.SetEditable(False)
self.SetSizer(sizer)
self.moneyCtrl = ctrl
def SetMoney(self, money):
self.moneyCtrl.SetValue(str(money))
class ChangerWidget(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, title="Main View")
sizer = wx.BoxSizer(wx.VERTICAL)
self.add = wx.Button(self, label="Add Money")
self.remove = wx.Button(self, label="Remove Money")
sizer.Add(self.add, 0, wx.EXPAND | wx.ALL)
sizer.Add(self.remove, 0, wx.EXPAND | wx.ALL)
self.SetSizer(sizer)
class Controller:
def __init__(self, app):
self.model = Model()
self.view1 = View(None)
self.view2 = ChangerWidget(self.view1)
self.MoneyChanged(self.model.myMoney.get())
self.view2.add.Bind(wx.EVT_BUTTON, self.AddMoney)
self.view2.remove.Bind(wx.EVT_BUTTON, self.RemoveMoney)
self.model.myMoney.addCallback(self.MoneyChanged)
self.view1.Show()
self.view2.Show()
def AddMoney(self, evt):
self.model.addMoney(10)
def RemoveMoney(self, evt):
self.model.removeMoney(10)
def MoneyChanged(self, money):
self.view1.SetMoney(money)
app = wx.App(False)
controller = Controller(app)
app.MainLoop()