Python设计模式:MVC模式

1. 什么是 MVC 模式?

MVC 模式是一种软件架构模式,用于将应用程序分为三个主要部分:模型(Model)、视图(View)和控制器(Controller)。这种分离使得应用程序的结构更加清晰,便于管理和扩展。

MVC 模式的组成部分:

  • 模型(Model)

    • 模型是应用程序的核心部分,负责管理数据和业务逻辑。它与数据库或其他数据源进行交互,处理数据的存储、检索和更新。
  • 视图(View)

    • 视图是用户界面的部分,负责显示数据和接收用户输入。它将模型中的数据呈现给用户,并在用户进行操作时更新显示。
  • 控制器(Controller)

    • 控制器是模型和视图之间的中介,负责处理用户输入并更新模型和视图。它接收用户的操作(如按钮点击),调用相应的模型方法,并更新视图。

MVC 模式的优点:

  • 分离关注点:MVC 模式将应用程序的不同部分分离,使得每个部分可以独立开发和维护。这种分离使得代码更加清晰,易于理解。
  • 可扩展性:由于模型、视图和控制器之间的解耦,开发者可以轻松地添加新功能或修改现有功能,而不影响其他部分。
  • 可测试性:MVC 模式使得单元测试变得更加容易,因为模型和控制器可以独立于视图进行测试。

2. 示例1:运动会计时器

实现一个运动会计时器应用,用户可以通过三个按钮来控制计时:开始计时、记录当前耗时和停止计时。每次点击"记录"按钮时,当前的耗时将被记录并显示在列表中。点击"停止"按钮将结束计时并显示最终耗时。

python 复制代码
import tkinter as tk
from tkinter import messagebox
import time


# 模型
class TimerModel:
    def __init__(self):
        self.start_time = None
        self.elapsed_time = 0
        self.records = []

    def start_timer(self):
        self.start_time = time.time()
        self.elapsed_time = 0  # 重置计时器为 0
        self.records.clear()  # 清除之前的记录

    def record_time(self):
        if self.start_time is not None:
            current_time = time.time()
            elapsed = current_time - self.start_time + self.elapsed_time
            self.records.append(elapsed)
            return elapsed
        return None

    def stop_timer(self):
        if self.start_time is not None:
            self.elapsed_time = time.time() - self.start_time + self.elapsed_time
            self.start_time = None
            return self.elapsed_time
        return None

    @staticmethod
    def format_time(seconds):
        milliseconds = int((seconds - int(seconds)) * 1000)
        seconds = int(seconds)
        minutes = seconds // 60
        seconds = seconds % 60
        return f"{minutes}m {seconds}s {milliseconds}ms"


# 视图
class TimerView:
    def __init__(self, master):
        self.master = master
        self.master.title("Sports Timer")
        self.master.geometry("400x400")

        self.record_listbox = tk.Listbox(master, font=("Arial", 14))
        self.record_listbox.pack(pady=20, fill=tk.BOTH, expand=True)

        self.start_button = tk.Button(master, text="Start", command=self.start)
        self.start_button.pack(pady=5)

        self.record_button = tk.Button(master, text="Record", command=self.record)
        self.record_button.pack(pady=5)

        self.stop_button = tk.Button(master, text="Stop", command=self.stop)
        self.stop_button.pack(pady=5)

        self.message_label = tk.Label(master, text="", font=("Arial", 12))
        self.message_label.pack(pady=10)

    def start(self):
        return True

    def record(self, elapsed_time):
        if elapsed_time is not None:
            formatted_time = TimerModel.format_time(elapsed_time)
            self.record_listbox.insert(tk.END, formatted_time)  # 显示记录的时间
            self.record_listbox.see(tk.END)  # 自动滚动到最新记录

    def stop(self, total_time):
        if total_time is not None:
            formatted_time = TimerModel.format_time(total_time)
            self.record_listbox.insert(tk.END, f"Total Time: {formatted_time}")  # 显示总时间
            self.record_listbox.see(tk.END)  # 自动滚动到最新记录

    def display_start_message(self):
        self.message_label.config(text="Timer started! Click 'Record' to log the time.")

    def clear_start_message(self):
        self.message_label.config(text="")  # 清除提示信息


# 控制器
class TimerController:
    def __init__(self, model, view):
        self.model = model
        self.view = view

        # 绑定按钮事件
        self.view.start_button.config(command=self.start_timer)
        self.view.record_button.config(command=self.record_time)
        self.view.stop_button.config(command=self.stop_timer)

    def start_timer(self):
        self.model.start_timer()
        self.view.record_listbox.delete(0, tk.END)  # 清除之前的记录
        self.view.display_start_message()  # 显示开始计时的提示

    def record_time(self):
        elapsed_time = self.model.record_time()
        self.view.record(elapsed_time)

    def stop_timer(self):
        total_time = self.model.stop_timer()
        self.view.stop(total_time)
        self.view.clear_start_message()  # 清除开始计时的提示


if __name__ == "__main__":
    root = tk.Tk()  # 创建主窗口
    model = TimerModel()  # 创建模型
    view = TimerView(root)  # 创建视图
    controller = TimerController(model, view)  # 创建控制器
    root.mainloop()  # 运行主循环
  1. 模型(Model)

    • TimerModel 类负责管理计时数据。它包含开始时间、经过时间和记录列表。
    • start_timer 方法开始计时,重置计时器为 0,并清除之前的记录。
    • record_time 方法计算当前经过的时间并将其添加到记录列表中。
    • stop_timer 方法计算总的经过时间并返回。
    • format_time 方法将时间格式化为"分钟:秒:毫秒"的格式。
  2. 视图(View)

    • TimerView 类负责用户界面的显示和用户输入的处理。它创建了一个列表框用于显示记录的时间和三个按钮(开始、记录、停止)。
    • start 方法用于开始计时。
    • record 方法接收经过的时间并将其格式化后显示在列表框中,同时调用 self.record_listbox.see(tk.END) 来自动滚动到最新记录。
    • stop 方法接收总的经过时间并将其显示在列表框中,同样调用 self.record_listbox.see(tk.END) 来确保最新记录可见。
  3. 控制器(Controller)

    • TimerController 类负责协调模型和视图之间的交互。它处理用户输入并更新模型和视图。
    • start_timer 方法调用模型的开始计时方法,并清除列表框中的记录,同时显示开始计时的提示。
    • record_time 方法调用模型的记录时间方法,并将结果传递给视图。
    • stop_timer 方法调用模型的停止计时方法,并将结果传递给视图,同时清除开始计时的提示。
  4. 客户端代码

    • if __name__ == "__main__": 块中,创建模型、视图和控制器的实例,并运行主循环。

运行上述代码时,将看到一个运动会计时器界面,包含一个显示记录时间的列表框和三个按钮(开始、记录、停止)。用户可以点击"开始"按钮开始计时,点击"记录"按钮记录当前的耗时(保留到毫秒),点击"停止"按钮结束计时并显示总耗时。同时,在点击"开始"时,文本面板会显示"计时器已启动!点击'记录'以记录时间。"在点击"停止"时,提示信息将被清除,并且列表框会自动滚动以显示最新记录。

相关推荐
英英_1 分钟前
python 爬虫框架介绍
开发语言·爬虫·python
大模型铲屎官1 小时前
【Python-Day 14】玩转Python字典(上篇):从零开始学习创建、访问与操作
开发语言·人工智能·pytorch·python·深度学习·大模型·字典
yunvwugua__1 小时前
Python训练营打卡 Day27
开发语言·python
Stara05112 小时前
基于多头自注意力机制(MHSA)增强的YOLOv11主干网络—面向高精度目标检测的结构创新与性能优化
人工智能·python·深度学习·神经网络·目标检测·计算机视觉·yolov11
Java致死2 小时前
设计模式Java
java·开发语言·设计模式
那雨倾城3 小时前
使用 OpenCV 将图像中标记特定颜色区域
人工智能·python·opencv·计算机视觉·视觉检测
LuckyTHP6 小时前
java 使用zxing生成条形码(可自定义文字位置、边框样式)
java·开发语言·python
mahuifa7 小时前
(7)python开发经验
python·qt·pyside6·开发经验
学地理的小胖砸8 小时前
【Python 操作 MySQL 数据库】
数据库·python·mysql
安迪小宝9 小时前
6 任务路由与负载均衡
运维·python·celery