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()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章