在 MVC 中实例化视图、模型和数据库

Instantiating views, models, and databases in MVC

我目前是 Python 的新手,正在学习 MVC 架构模式。为了简单和便于解释,假设我有 3 类。 (模型、视图和控制器)。

class Controller  
  def __init__(self):
    self.view = View()
    self.model = Model()

  def some_function(self):
    return self.model.add_things(1,2)

class Model
  def __init__(self):
    pass

  def add_things(self, x, y):
    return x + y

class View:
  def __init__(self):
    pass

像上面那样将我的视图和模型实例化为 Controller 的实例变量是正常做法吗?

还是在控制器文件的顶部手动导入文件(即导入模型)并直接在控制器中调用方法更好?

from Model import Model 
from View import View

class Controller  
  def __init__(self):
     pass

 def some_function(self):
     return Model.add_things(1, 2)

class Model
  def __init__(self):
    pass

  def add_things(self, x, y):
    return x + y

class View:
  def __init__(self):
    pass

我认为你的例子不太符合标准。在你的第二个代码片段中,你仍然(大概)要处理 classes(ModelView), 所以这段代码对我来说有点奇怪:

from Model import Model 
from View import View

class Controller  

    def some_function(self):
        # How are you calling the method on the class and not the instance?
        return Model.add_things(1, 2)

您必须执行类似 return Model().add_things(1, 2) 的操作来获取一个实例,从中调用 add_things 方法(除非该函数被修饰为 classmethod)。但是,这实际上没有任何意义,我敢打赌你可能不是那个意思。您实际上想要的是在构造函数中初始化对象与使用全局声明的实例之间的区别,所以 像这样 :

# It seems that for your question, it shouldn't really matter whether the 
# class `Model` is imported or declared inside the same module. So it could 
# be either way.
# 1) class Model(): pass
# 2) from Model import Model    

# This would initialize `Model` at the module-level
modelobject = Model()

class Controller  

    def some_function(self):
        # And then it would be possible to use it as you described.
        return modelobject.add_things(1, 2)

回到问题...

为了回答你,我首先必须让你意识到你真正在问什么重点是从外部导入 ModelView 与在它们正在使用的同一模块中定义它们没有任何错误或远程争议在,所以问这个问题真的没有多大意义;事实上,这真的取决于您的程序结构,更一般地说,取决于您的项目 有多大。越大越复杂,这些 classes 或 classes 的集合就越不可能混合在同一个模块中。他们很快就会被分成不同的模块。

所以据我所知,你真正的问题是最好在 Controller 的构造函数中初始化 ModelView 对象还是将它们用作您可以从 Controller class 调用的全局实例。坦率地说,我认为您真正要问的是类似于全局实例模式的东西(例如,类似于 Singleton class)。

您还没有具体使用术语Singleton,但正在寻求一种使用全局声明实例的方法class 闻起来很像你要问的。

您可以阅读它的陷阱 here, here or here

更好的方法是 Dependency Injection

要引用您的原始示例,它可能 - 对于代码层次结构中较低的对象 - 最好使用以下方法(以在整个过程中获得 单个实例 程序):

class SubController
    def __init__(self, modelobject, viewobject):
        self.view = viewobject
        self.model = modelobject

换句话说,它与 单例 没有什么不同,因为您实际上是在使用 单实例 ,如果这确实是您需要的东西。但是,它不是通过声明一个全局实例(这会引入耦合和链接文章中讨论的许多其他问题)来工作的,而是通过让 class 通过调用上下文获取其依赖项(这具有相当大的优势)来工作的。因此,您直接通过构造函数方法传递 ModelView 对象,而不是直接在 classes 中实例化它们(如您的示例)或使用全局声明的变量获取它们。

当然,您总是有 main class 或函数,您可以在其中实例化这些对象并从那里传递它们。这种方法的好处是以后会更加灵活!