更新进度栏-MVP模式

问题描述 投票:0回答:1

我正在研究MVP模式,但是为了实时更新进度条,很难遵循这些原则。据我了解,Presenter会检查Model中是否有任何更新,然后输出结果,因此在Model中没有Presenter的实例化,只有Presenter应该实例化Model和View。

我的问题是:如何遵循MVP原则更新进度条?我当然可以从Model调用presenter.update_progress_bar(i,total),但这会违反MVP原则。

这是一个最小的工作示例:

PS:目前,我正在使用CLI。

/ main.py

import modules

def main():
    modules.View(modules.Presenter).run()

if __name__ == "__main__":
    main()

/模块/ __初始化__。PY

from modules.Model.Model import Model
from modules.Model.progressbar import ProgressBar
from modules.View.View import View
from modules.Presenter.Presenter import Presenter

/模块/型号/ Model.py

class Model:
def __init__(self):
    pass

def long_process(self):
    import time
    for i in range(10):
        time.sleep(0.1)
        print("Update the progress bar.")
    return True

/模块/型号/ progressbar.py

# MIT license: https://gist.github.com/vladignatyev/06860ec2040cb497f0f3
import sys
class ProgressBar:
def progress(count, total, status=''):
    bar_len = 60
    filled_len = int(round(bar_len * count / float(total)))

    percents = round(100.0 * count / float(total), 1)
    bar = '=' * filled_len + '-' * (bar_len - filled_len)

    sys.stdout.write('[%s] %s%s ...%s\r' % (bar, percents, '%', status))
    sys.stdout.flush()

/模块/视图/ View.py

import sys
class View:
def __init__(self, presenter):
    self.presenter = presenter(self)

def run(self):
    self.presenter.long_process()

def update_progress_bar(self, msg):
    sys.stdout.write(msg)

def hide_progress_bar(self, msg):
    sys.stdout.write(msg)

def update_status(self, msg):
    print(msg)

/模块/主持人/ Presenter.py

class Presenter:
def __init__(self, view):
    import modules
    self.model = modules.Model()
    self.view = view

def long_process(self):
    if self.model.long_process():
        self.view.update_status('Long process finished correctly')
    else:
        self.view.update_status('error')

def update_progress_bar(self, i, total):
    from modules import ProgressBar
    ProgressBar.progress(i, total)
    self.view.update_progress_bar(ProgressBar.progress(i, total))

def end_progress_bar(self):
    self.view.end_progress_bar('\n')

我可以做:

class Model:
def __init__(self, presenter):
    self.presenter = presenter  # Violation of MVP

def long_process(self):
    import time
    for i in range(10):
        time.sleep(0.1)
        self.presenter.update_progress_bar(i, 10)  # Violation of MVP
        print("Update the progress bar.")
    return True

但是这是错误的,因为模型现在实例化了Presenter。有什么建议吗?

python python-3.x oop progress-bar mvp
1个回答
0
投票

使用回调:

import time

class Model:
    def long_process(self, notify=lambda current, total: None):
        for i in range(10):
            time.sleep(0.1)
            notify(i, 10)  
        return True



class Presenter:
    def long_process(self):
        result = self.model.long_process(lambda c, t: self.update_progress_bar(c, t)):
        if result:
            self.view.update_status('Long process finished correctly')
        else:
            self.view.update_status('error')

这使您的模型独立于客户端代码,同时仍然允许它(我的意思是模型)通知其调用者。

作为附带说明,您的代码中有很多东西完全是非Python的:

1 //您不必将每个类放在一个单独的模块中(在Python中实际上被认为是反模式),而在嵌套子模块中则更少(Python Zen:“扁平比嵌套更好”)。

2 //当普通函数就足够时,您不必使用类(提示:Python函数是对象……实际上,Python中的所有对象都是对象)-您的ProgressBar类没有状态,只有一个方法,因此它可能只是一个普通函数(Python Zen:“简单胜于复杂”)。

3 / imports should be at the top of the module,不在函数中(如果必须将它们放入函数中以解决循环依赖性问题,那么正确的解决方案是重新考虑设计以避免循环依赖性)。

4 / module names should be all_lower

© www.soinside.com 2019 - 2024. All rights reserved.