Python设计模式:模型-视图-控制器模式

设计模式九:模型-视图-控制器模式

什么是模型-视图-控制器模式

模式的名称来自用来切分软件应用的三个主要部分:模型部分,视图部分和控制器部分,这是一种架构模式。
模型:代表着应用的信息本源,包含和管理逻辑,数据,状态以及应用规则。
视图:是模型的可视化表现。
控制器:模型与视图之间的链接、粘附。
模型与视图之间的所有通信都是通过控制器进行的。

使用优势

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版权协议,转载请附上原文出处链接和本声明。