行爲型--MVC模式

什麼是模型-視圖-控制(MVC)模型


在介紹模型-視圖-控制(Model-View-Controller,MVC)模型之前,我們先介紹一個概念:關注點分離原則
關注點分離原則(Separation of Concerns, SoC) 是軟件工程相關的設計原則之一。 SoC原則背後的思想是將一個應用切分成不同的部分,每個部分只負責解決自身問題。分層設計中的層(數據訪問層、業務邏輯層和表示層等)即是關注點。

MVC模式: 又叫做 模型–視圖–控制,是 SoC原則 在面向對象中的實現。MVC 也被廣泛稱之爲架構模式;MVC 意爲把組織分爲三個部分:模型部分視圖部分控制器

  • 模型 :是組織的核心部分,負責訪問數據,管理應用狀態;
  • 視圖 :是 模型 的外在表現,提供展示和交互功能;不涉及到對數據的處理,例如用戶的操作界面;
  • 控制器 :是 模型視圖 的連接器,模型視圖 通過 控制器 進行通信;每個視圖應該有一個與之匹配的控制器;控制器 使得 模型視圖 可以解耦;

三者之間的關係如下圖所示:

在這裏插入圖片描述


MVC 模型的應用場景


在實際的使用過程中,Web 框架 Web2py 就是一個支持 MVC 模式的輕量級 Python 框架。Django 也是一個 MVC 框架。不過稍有不同,控制器 被稱爲 視圖視圖 被稱爲 模板。 Django使用名稱 模型—模板—視圖( Model-Template-View, MTV)來替代MVC。MVC 模型的使用適合以下場景:

  • 視圖模型 的分離允許美工一心搞 UI8部分,程序員一心搞開發,不會相互干擾。
  • 由於 視圖模型 之間的松耦合,每個部分可以單獨修改/擴展,不會相互影響。例如,添加一個新視圖的成本很小,只要爲其實現一個 控制器 就可以了。

MVC 模型的優點


  1. MVC 模型最大的優點就是 松耦合視圖模型松耦合,每一個部分可以單獨的修改和擴展,不會相互影響。
  2. 無需修改模型,就可以實現多個視圖 連接同一個 模型,因爲每一個 視圖 都有一個與之相應的 連接器連接器 通常被設計成規模瘦小。如下圖所示:

在這裏插入圖片描述


使用 MVC 模型的注意事項


在從頭開始實現 MVC 時,請確保創建的 模型很智能視圖很傻瓜控制器很瘦

  • 模型很智能 的原則爲:
    • 包含所有業務規則和邏輯;
    • 處理應用的狀態;
    • 訪問應用數據(包括數據庫、雲);
    • 不依賴 UI;
  • 視圖很傻瓜 的原則爲:
    • 展示數據;
    • 運行用戶與其交互;
    • 僅做最小的數據處理;
    • 不存儲任何數據;
    • 不能直接訪問數據;
    • 不包含業務規則和邏輯;
  • 控制器很瘦 的原則爲:
    • 在運行過程中,可以更新視圖和模型;
    • 如果需要,在數據傳遞給模型和視圖之前進行處理;
    • 不展示數據;
    • 不直接訪問應用數據;
    • 不包含業務規則和邏輯;

MVC 模型的例子


利用 MVC 模型實現一個搜索並顯示名人名言的應用。想法很簡單:用戶輸入一個數字,然後就能看到與這個數字相關的名人名言。
在這個應用中,涉及到三個類:模型類視圖類連接器類;三者的組織關係如下所示:


模擬數據庫

名人名言存儲在一個 quotes 元組中。這種數據通常是存儲在數據庫、文件或其他地方,只有模型能夠直接訪問它。

# 模擬數據庫
quotes = ('A man is not complete until he is married. Then he is finished.',
          'As I said before, I never repeat myself.',
          'Behind a successful man is an exhausted woman.',
          'Black holes really suck...', 'Facts are stubborn things.')

模型-視圖-控制器設計


- 模型極爲簡約,只有一個 `get_quote()` 方法,基於索引n從quotes元組中返回對應的名人名言(字符串); - 視圖有三個方法,分別是 `select_quote()、show()、 error()`。 - `select_quote()` 用於讀取用戶的選擇; - `show()` 用於在屏幕上輸出一句名人名言(或者輸出提示信息 `Not found`!); - `error()` 用於在屏幕上輸出一條錯誤消息; - 控制器負責協調。 - ` __init__()` 方法初始化模型和視圖。 - `run()` 方法校驗用戶提供的名言索引,然後從模型中獲取名言,並返回給視圖展示;

具體代碼如下所示:

# 模型
class QuoteModel:

    # 從數據庫中讀取名人名言
    def get_quote(self, n):
        try:
            value = quotes[n]
        except IndexError as err:
            value = 'Not found!'
        return value

# 視圖
class QuoteTerminalView:

    # 選擇名人名言
    def select_quote(self):
        return input('Which quote number would you like to see?')

    # 顯示名人名言
    def show(self, quote):
        print('And the quote is: "{}"'.format(quote))

    # 顯示錯誤
    def error(self, msg):
        print('Error: {}'.format(msg))

# 控制器
class QuoteTerminalController:

    def __init__(self):
        self.model = QuoteModel() # 模型實例
        self.view = QuoteTerminalView() # 視圖實例

    def run(self):
        valid_input = False

        # 調用視圖模型獲取用戶選擇
        while not valid_input:
            n = self.view.select_quote() # 提供交互
            try:
                n = int(n)
            except ValueError as err:
                self.view.error("Incorrect index '{}'".format(n))
            else:
                valid_input = True

        # 把數據傳遞給模型
        quote = self.model.get_quote(n)

        # 視圖顯示數據
        self.view.show(quote)

應用上述代碼

def main():
    controller = QuoteTerminalController()
    while True:
        controller.run()

if __name__ == '__main__':
    main()

源碼在這裏


參考資料


  1. 《精通Python設計模式》
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章