关于如何在Django中实现服务的约定?来自Java背景,我们为业务逻辑创建服务,并在需要时将它们“注入”。
不知道我是否以错误的方式使用python / django,但我需要连接到第三方API,因此我使用的是api_service.py文件。问题是,我想将此服务定义为一个类,并且在Java中,我可以在需要的任何地方注入该类,并且它的行为或多或少像一个单例。是否可以在Django中使用类似的东西,还是应该将服务构建为单例并将实例放置在某个地方,甚至只具有单独的函数且没有类?
请您参考如下方法:
TL; DR如果没有更多细节很难说,但是有可能您只需要一个带有几个简单函数的模块,或者最多只有几个简单的类。
最长的答案:
Python is not Java。您当然可以(技术上来说)使用Java式的设计,但这通常不是最好的选择。
您对要解决的问题的描述太含糊,无法给出具体的答案,但我们至少可以为您提供一些提示和指示(无双关语):
1 /一切都是对象
在python中,一切(好了,您可以在分配的RHS上找到的一切)都是一个对象,包括模块,类,函数和方法。
结果之一是,您不需要任何复杂的框架来进行依赖项注入-您只需将所需的对象(模块,类,函数,方法等)作为参数传递就可以了。
另一个结果是,您不必为所有内容都需要类-一个简单的函数或模块就足够了。
一个典型的用例是策略模式,在Python中,该策略模式通常仅使用回调函数(或任何其他可调用的FWIW)实现。
2 /一个python模块是一个单例。
如上所述,在运行时,python模块是一个对象(类型为module),其属性是在模块顶层定义的名称。
除某些(病理性)极端情况外,对于给定的流程,python模块仅导入一次,并保证是唯一的。结合python的“全局”作用域实际上只是“模块级”全局这一事实,这使模块成为适当的单例,因此实际上已经内置了这种设计模式。
3 /一个python类几乎是一个单例
Python类也是对象(直接或间接地为type类型的实例),并且python具有classmethods(对类本身起作用而不是对当前实例起作用的方法)和类级属性(属于类对象本身,而不是实例对象),因此,如果您编写的类仅具有类方法和类属性,则从技术上讲,您具有一个单例-您可以直接使用该类,也可以通过实例使用该类,而没有任何区别,因为可以调用类方法在实例上也是如此。
这里wrt /“ modules as singletons”的主要区别在于使用类可以使用继承...
4 / python有可调用项
Python具有“可调用”对象的概念。 “ callable”是一个对象,其类实现__call__()运算符),每个这样的对象都可以被调用,就好像它是一个函数一样。
这意味着您不仅可以将函数用作对象,还可以将对象用作函数-IOW,内置了“ functor”模式。这使得在代码的一部分中“捕获”某些上下文并在另一部分中使用该上下文进行计算非常容易。
5 / python类是工厂
Python没有new关键字。 Pythonc类是可调用的,实例化仅通过调用该类即可完成。
这意味着您实际上可以以相同的方式使用类或函数来获取实例,因此也内置了“工厂”模式。
6 / python具有computed attributes
除了最明显的应用程序(用一对getter / setter替换公共属性而不破坏客户端代码)之外,这(与可调用对象等其他功能结合)可以证明非常强大。实际上,that's how functions defined in a class become methods
7 / Python是动态的
Python的对象(通常)是基于dict的(有例外,但这些例外很少,并且大多数是低级C编码类),这意味着您可以动态添加/替换(甚至删除)属性和方法(因为方法是属性)基于每个实例或每个类别。
虽然这不是您无缘无故要使用的功能,但它仍然是一个非常强大的功能,因为它允许动态自定义对象(记住类也是对象),从而允许比您可以做的事情更复杂的对象和类创建方案以静态语言。
但是Python的动态性质更进一步-您可以使用类装饰器和/或元类来抑制类对象的创建(您可能想看看Django模型的源代码作为一个具体示例),甚至只是动态地创建一个使用其元类的新类以及函数和其他类级属性的字典。
同样,这确实可以使看似复杂的问题变得轻而易举地解决(并避免了很多样板代码)。
实际上,Python公开并允许您了解其大部分内部信息(对象模型,属性解析规则,导入机制等),因此,一旦您了解了整个设计以及如何将所有内容融为一体,您就可以真正掌握代码的大多数方面运行。
Python不是Java
现在我知道所有这些看起来都像是供应商的目录,但重点是要突出说明Python与Java有何不同以及为什么规范的Java解决方案(或(至少)这些解决方案的规范的Java实现)通常不能很好地移植到Python世界。并不是说它们根本不起作用,只是Python通常具有更简单(和更简单的IMHO)方式来实现常见(和较不常见)设计模式。
wrt /您的具体用例,您将不得不发布更详细的描述,但是Django项目中的“连接到第三部分API”(我假设是REST api吗?)是如此琐碎,以至于实际上并不需要太多设计方面的考虑。
