您的位置:首页 > 编程语言 > Python开发

python编程(基于订阅模式的mvc实现)

2017-12-27 23:39 120 查看
【声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

基于mvc方式开发的客户端软件很多,但是用订阅方式实现mvc,我今天还是第一次看到。今天看到一篇英文文献,十分有意思,原有链接在

现在假设有两个页面,一个页面要存钱、取钱,另外一个要显示。当然,这中间少不了controller和model,看看链接中的code是怎么处理mvc关系的。

首先是model和controller代码,也是应用的入口代码,

"""
Adapted from wxPython website at http://wiki.wxpython.org/ModelViewController/. :copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
:license: BSD, see LICENSE.txt for details.
"""

import wx

from pubsub import pub

print('pubsub API version', pub.VERSION_API)

# notification
from pubsub.utils.notification import useNotifyByWriteFile
import sys

useNotifyByWriteFile(sys.stdout)

# the following two modules don't know about each other yet will
# exchange data via pubsub:
from wx_win1 import View
from wx_win2 import ChangerWidget

class Model:
def __init__(self):
self.myMoney = 0

def addMoney(self, value):
self.myMoney += value
# now tell anyone who cares that the value has been changed
pub.sendMessage("money_changed", money=self.myMoney)

def removeMoney(self, value):
self.myMoney -= value
# now tell anyone who cares that the value has been changed
pub.sendMessage("money_changed", money=self.myMoney)

class Controller:
def __init__(self):
self.model = Model()

# set up the first frame which displays the current Model value
self.view1 = View()
self.view1.setMoney(self.model.myMoney)

# set up the second frame which allows the user to modify the Model's value
self.view2 = ChangerWidget()

self.view1.Show()
self.view2.Show()

pub.subscribe(self.changeMoney, 'money_changing')

def changeMoney(self, amount):
if amount >= 0:
self.model.addMoney(amount)
else:
self.model.removeMoney(-amount)

if __name__ == "__main__":
app = wx.App()
c = Controller()
sys.stdout = sys.__stdout__

print('---- Starting main event loop ----')
app.MainLoop()
print('---- Exited main event loop ----')


然后是一个显示窗口的代码,

"""
:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
:license: BSD, see LICENSE.txt for details.
"""

import wx
from pubsub import pub

class View(wx.Frame):
def __init__(self, parent=None):
wx.Frame.__init__(self, parent, -1, "Main View")

sizer = wx.BoxSizer(wx.VERTICAL)
text = wx.StaticText(self, -1, "My Money")
ctrl = wx.TextCtrl(self, -1, "")
sizer.Add(text, 0, wx.EXPAND | wx.ALL)
sizer.Add(ctrl, 0, wx.EXPAND | wx.ALL)

self.moneyCtrl = ctrl
ctrl.SetEditable(False)
self.SetSizer(sizer)

# subscribe to all "MONEY CHANGED" messages from the Model
# to subscribe to ALL messages (topics), omit the second argument below
pub.subscribe(self.setMoney, "money_changed")

def setMoney(self, money):
self.moneyCtrl.SetValue(str(money))


最后是存钱、取钱窗口的代码,

"""
Widget from which money can be added or removed from account.
:copyright: Copyright since 2006 by Oliver Schoenborn, all rights reserved.
:license: BSD, see LICENSE.txt for details.
"""

import wx
from pubsub import pub

class ChangerWidget(wx.Frame):
CHANGE = 10  # by how much money changes every time click

def __init__(self, parent=None):
wx.Frame.__init__(self, parent, -1, "Changer View")

sizer = wx.BoxSizer(wx.VERTICAL)
self.add = wx.Button(self, -1, "Add Money")
self.remove = wx.Button(self, -1, "Remove Money")
sizer.Add(self.add, 0, wx.EXPAND | wx.ALL)
sizer.Add(self.remove, 0, wx.EXPAND | wx.ALL)
self.SetSizer(sizer)

self.add.Bind(wx.EVT_BUTTON, self.onAdd)
self.remove.Bind(wx.EVT_BUTTON, self.onRemove)

def onAdd(self, evt):
print('-----')
pub.sendMessage("money_changing", amount=self.CHANGE)

def onRemove(self, evt):
print('-----')
pub.sendMessage("money_changing", amount=- self.CHANGE)


通过这一些类的操作,大家可以看一下整个消息流是怎么从money_changing变成money_changed流程的。

当然,这里没有给出publish-subscrib的代码,没关系,我们可以看另外一种简单的实现办法,或许对我们有所触动。

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


大家可以利用这个案例好好思考一下mvc是如何利用publish-subscribe的方式将他们串在一起的。目前在wxpython中可以直接调用这个类,比如

from wx.lib.pubsub import Publisher
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐