美文网首页
python设计模式9模型视图控制器MVC(model-view

python设计模式9模型视图控制器MVC(model-view

作者: python测试开发 | 来源:发表于2021-07-12 08:55 被阅读0次

    关注点分离(SoC separation of concerns)师软件工程相关的设计原则之一。SoC原则背后的想法是将应用程序分成不同的部分,每个部分解决一个单独的问题。这种关注点的例子是分层设计中使用的层(数据访问层、业务逻辑层、表现层等等)。使用SoC原则可以简化软件应用程序的开发和维护。

    MVC模式只不过是将SoC原则应用于OOP。该模式的名称来自于用于分割软件应用的三个主要组件:模型、视图和控制器。MVC被认为是一种架构模式,而不是一种设计模式。架构模式和设计模式的区别在于,前者比后者的范围更广。然而,MVC太重要了,不能因为这个原因就跳过。即使我们永远不需要从头开始实现它,我们也需要熟悉它,因为所有常见的框架都使用MVC或其变种。

    模型是核心组件。它代表知识。它包含并管理应用程序的(业务)逻辑、数据、状态和规则。视图是模型的可视化表示。视图的例子有计算机GUI、计算机终端的文本输出、智能手机的应用GUI、PDF文档、饼状图、柱状图等等。视图只显示数据,它并不处理数据。控制器是模型和视图之间的纽带/粘合剂。模型和视图之间的所有通信都通过控制器进行。

    典型的使用MVC的应用程序,在初始屏幕呈现给用户后,其使用情况如下。

    • 用户通过点击(输入、触摸等)按钮来触发一个视图。
    • 视图将用户的操作告知控制器
    • 控制器处理用户输入并与模型进行交互
    • 模型执行所有必要的验证和状态变化,并通知控制器应该做什么。
    • 控制器指示视图按照模型给出的指示,适当地更新和显示输出。

    你可能想知道,为什么控制器部分是必要的?我们就不能跳过它吗?可以,但这样我们就会失去很大的好处:可以在不修改模型的情况下使用多个视图(甚至同时使用,如果我们想这样的话)。为了实现模型和其表现形式之间的解耦,每个视图通常都需要自己的控制器。如果模型直接与特定的视图通信,我们就不能使用多个视图(或者至少,不能以干净和模块化的方式)。

    真实世界的例子

    MVC是应用于OOP的SoC原则。SoC原则在现实生活中被大量使用。例如,如果你建造一栋新房子,你通常会指派不同的专业人员去做。1)安装水管和电;以及,2)喷漆。

    在餐馆里,服务员接受订单并为顾客提供菜肴,但饭菜是由厨师烹制的。

    在Web开发中,有几个框架采用了MVC的思想。

    • Web2py框架MVC模式的轻量级Python框架。
    • Django也是一个MVC框架,尽管它使用不同的命名规则。控制器被称为视图,而视图被称为模板。Django使用的是Model-Template-View(MTV)这个名字。根据Django的设计者,视图描述了用户看到的数据是什么,因此,它使用视图这个名字作为特定URL的Python回调函数。Django中的模板一词是用来将内容和表现形式分开的。它描述了用户是如何看到数据的,而不是看到哪些数据。

    应用

    MVC是一个非常通用和有用的设计模式。事实上,所有流行的Web框架(Django、Rails和Symfony或Yii)和应用程序框架(iPhone SDK、Android和QT)都使用了MVC或其变体--模型-视图-适配器(MVA)、模型-视图-呈现器(MVP),等等。然而,即使我们不使用这些框架,在我们自己身上实现该模式也是有意义的,因为它提供了以下好处。

    • 视图和模型之间的分离使得图形设计师可以专注于UI部分,程序员可以专注于开发,而不会相互干扰。
    • 由于视图和模型之间的松散耦合,每个部分都可以被修改/扩展而不影响其他部分。例如,添加一个新的视图是微不足道的。只要为它实现一个新的控制器。
    • 每个部分的维护都很容易,因为责任很明确。

    当从头开始实现MVC时,要确保你创建了智能模型、瘦控制器和傻瓜视图。

    模型被认为是智能的,因为:

    • 包含所有的验证/业务规则/逻辑
    • 处理应用程序的状态
    • 可以访问应用程序的数据(数据库、云等)。
    • 不依赖于UI

    控制器被认为是瘦的,因为。

    • 当用户与视图交互时更新模型
    • 当模型发生变化时更新视图
    • 如有必要,在向模型/视图传递数据之前对其进行处理
    • 不显示数据
    • 不直接访问应用程序的数据
    • 不包含验证/业务规则/逻辑

    视图被认为是傻瓜的,因为:

    • 显示数据
    • 允许用户与之交互
    • 只做最小的处理,通常由模板语言提供(例如,使用简单的变量和循环控制)。
    • 不存储任何数据
    • 不直接访问应用程序的数据
    • 不包含验证/业务规则/逻辑

    如果你正在从头开始实施MVC,并想知道你是否做对了,你可以试着回答一些关键问题。

    • 应用程序的GUI是否可以换肤?你能多容易地改变它的皮肤/外观和感觉?你能让用户在运行时改变你的应用程序的皮肤吗?如果这并不简单,那就意味着你的MVC实现出了问题。

    • 如果你的应用程序没有GUI(例如,如果它是一个终端应用程序),添加GUI支持有多难?或者,如果添加GUI无关紧要,那么添加视图以在图表(饼图、柱状图等)或文档(PDF、电子表格等)中显示结果是否容易?如果这些变化不是很琐碎(只是创建一个新的控制器,并在其上附加一个视图,而不修改模型),那么MVC就没有正确实现。

    如果你确保这些条件得到满足,与不使用MVC的应用程序相比,你的应用程序将更加灵活和可维护。

    实例

    我们用非常简单的例子向你展示如何从头开始实现MVC:报价打印机。用户输入一个数字,看到与该数字相关的报价。报价被存储在元组中,实际应用多存在数据库、文件等,只有模型可以直接访问它。

    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.'
    ) 
     
    class QuoteModel: 
        def get_quote(self, n): 
            try: 
                value = quotes[n] 
            except IndexError as err: 
                value = 'Not found!' 
            return value 
     
    class QuoteTerminalView: 
        def show(self, quote): 
            print(f'And the quote is: "{quote}"') 
     
        def error(self, msg): 
            print(f'Error: {msg}') 
     
        def select_quote(self): 
            return input('Which quote number would you like to see? ') 
     
    class QuoteTerminalController: 
        def __init__(self): 
            self.model = QuoteModel() 
            self.view = QuoteTerminalView() 
     
        def run(self): 
            valid_input = False 
            while not valid_input: 
                try: 
                    n = self.view.select_quote() 
                    n = int(n) 
                    valid_input = True 
                except ValueError as err: 
                    self.view.error(f"Incorrect index '{n}'") 
            quote = self.model.get_quote(n) 
            self.view.show(quote) 
     
    def main(): 
        controller = QuoteTerminalController() 
        while True: 
            controller.run() 
     
    if __name__ == '__main__': 
        main()
    

    这个模型只有一个 get_quote() 方法,根据它的索引 n 返回 quotes 元组的报价 (字符串)。

    视图有三个方法:show(),用来在屏幕上打印一个引用(或消息Not found!),error(),用来在屏幕上打印一个错误信息,select_quote(),读取用户的选择。这可以从下面的代码中看出。

    控制器做协调工作。init()方法初始化模型和视图。run()方法验证用户给出的报价指数,从模型中获得报价,并将其传回给视图显示,如下代码所示。

    最后但同样重要的是,main()函数初始化并启动控制器。

    相关文章

      网友评论

          本文标题:python设计模式9模型视图控制器MVC(model-view

          本文链接:https://www.haomeiwen.com/subject/jymfpltx.html