设计模式九:模型-视图-控制器模式
什么是模型-视图-控制器模式
模式的名称来自用来切分软件应用的三个主要部分:模型部分,视图部分和控制器部分,这是一种架构模式。
模型:代表着应用的信息本源,包含和管理逻辑,数据,状态以及应用规则。
视图:是模型的可视化表现。
控制器:模型与视图之间的链接、粘附。
模型与视图之间的所有通信都是通过控制器进行的。
使用优势
1.无需修改模型就能使用多个视图的能力
2.为了实现模型与其表现之间的解耦,每个视图通常都需要属于它的控制器
3.视图与模型的分离允许美工和程序员不会互相干扰
4.视图与模型之间是松耦合,每个部分可以单独修改/扩展,不会相互影响
5.职责分明,维护简单
典型案例
用户通过点击某个按钮出发一个视图,视图把用户操作告知控制器,控制器处理用户输入,并与模型交互,模型执行所有必要的检验和状态改变,并通知控制器应该做什么,控制器按照模型给出的指令,知道视图适当的更新和显示输出。
使用注意
从头实现此模式,确保创建的模型很智能,控制器很瘦,视图很傻瓜
智能模型:
包含所有的校验、业务规则、逻辑
处理应用的状态
访问应用数据
不依赖UI
瘦控制器:
在用户与视图交互时,更新模型
模型改变时,更新视图
如果需要,在数据传递给模型、视图、之前进行处理
不展示数据
不直接访问应用数据
不包含校验、业务规则、逻辑
傻瓜视图:
展示数据
允许用户与其交互
仅做最小的数据处理,通常由一种模板语言提供处理能力
不存储任何数据
不直接访问应用数据
不包含校验、业务规则、逻辑
补充知识
软件工程相关的设计原则之一:关注点分离。将一个应用切分成不同的部分,每个部分解决一个单独的关注点,能简化软件应用的开发和维护
实例代码
import wx
import wx.xrc
import cv2
import numpy
from PIL import Image
import time
import random
import threading
class Model:
def __init__(self):
pass
def getvalue(self):
data = []
for i in range(200):
data_1 = []
for j in range(500):
x = random.randint(0,256)
data_1.append(x)
data.append(data_1)
a = numpy.array(numpy.uint8(data))
im = Image.fromarray(a)
im1 = im.convert('RGB')
idata = numpy.array(im1)
image_data = wx.BitmapFromBuffer(500,200,idata)
return image_data
class View ( wx.Frame ):
clickdown = False
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
bSizer1 = wx.BoxSizer( wx.VERTICAL )
bSizer2 = wx.BoxSizer( wx.VERTICAL )
self.m_button1 = wx.Button( self, wx.ID_ANY, u"Click", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.m_button1, 0, wx.ALL|wx.EXPAND, 5 )
self.m_bitmap1 = wx.StaticBitmap( self, wx.ID_ANY, wx.NullBitmap, wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer2.Add( self.m_bitmap1, 1, wx.ALL|wx.EXPAND, 5 )
bSizer1.Add( bSizer2, 1, wx.EXPAND, 5 )
self.SetSizer( bSizer1 )
self.Layout()
self.Centre( wx.BOTH )
# Connect Events
self.m_button1.Bind( wx.EVT_BUTTON, self.Click )
def __del__( self ):
pass
# Virtual event handlers, overide them in your derived class
def Click( self, event ):
self.clickdown = True
event.Skip()
def show(self,image):
self.m_bitmap1.SetBitmap(image)
class Controller:
def __init__(self):
self.view = View(None)
self.model = Model()
self.view.Show()
def run(self):
def threadrun():
while True:
event = self.view.clickdown
if event:
image = self.model.getvalue()
self.view.show(image)
self.view.clickdown = False
t = threading.Thread(target=threadrun,args=())
t.start()
if __name__ == "__main__":
app = wx.App()
controller = Controller()
controller.run()
app.MainLoop()
版权声明:本文为youngdianfeng原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。