在希望创建派生单例时使用 Python 模块的替代方案

71 阅读3分钟

在 Python 项目中,我们需要为用户提供各种概念的单个实例,我们称之为“dog”,“cat”和“parrot”。有些功能是它们共享的,例如sleep(),eat()和is_dead(),我们希望将这些功能放入“pet”概念中以实现代码重用。可以有多个宠物,但每种类型只有一个宠物。

我们认为不可能让 Python 模块继承另一个模块,因此,如果我们只想使用模块,就必须抛弃“pet”概念,并且在“dog”,“cat”和“parrot”模块中重复代码(sleep、eat 等)。或者创建一个“pet”模块,然后在其他每个模块中使用“from pet import *”,但据我们所知,这被认为是一种不佳实践。

huake_00066_.jpg 或者,我们可以创建一个“pet”类(派生自一个实现单例基类的),然后从该类派生“dog”,“cat”和“parrot”类。但是,我们看到大多数关于 Python 中单例模式的讨论都暗示该模式不是一个好主意。

因此,我们希望避免三种我们认为是不好的做法:

  1. 不同源文件之间的代码重复
  2. 使用“from x import *”
  3. 使用单例设计模式

但是,通过上述任何解决方案都无法实现所有这三点。我们倾向于使用单例设计模式,因为它看起来是“最不差”的选择。有没有办法在避免所有三个问题且不会引入任何其他不良实践的情况下实现我们的目标?

2. 解决方案

我们可以使用称为“组合”的设计模式来解决此问题。组合允许我们将对象组合在一起以形成新的对象,而无需继承。我们可以创建一个“pet”类,其中包含共享功能,例如sleep(),eat()和is_dead()。然后,我们可以创建一个“dog”类,其中包含dog特有的功能,例如bark()。我们可以通过将“pet”对象作为参数传递给“dog”类的构造函数来创建“dog”实例。

class Pet:
    def __init__(self, name):
    http://www.jshk.com.cn/mb/reg.asp?kefu=xiaoding;//爬虫IP免费获取;
        self.name = name

    def sleep(self):
        print(f'{self.name} is sleeping.')

    def eat(self):
        print(f'{self.name} is eating.')

    def is_dead(self):
        return False


class Dog(Pet):
    def __init__(self, name):
        super().__init__(name)

    def bark(self):
        print(f'{self.name} is barking.')


my_dog = Dog('Fido')
my_dog.sleep()
my_dog.eat()
my_dog.bark()

此代码会输出以下内容:

Fido is sleeping.
Fido is eating.
Fido is barking.

使用组合模式,我们可以避免三种我们认为是不好的做法:

  1. 不同源文件之间的代码重复:我们可以将共享功能放在“pet”类中,而将特定于每种类型的功能放在各自的类中。
  2. 使用“from x import *”:我们不必在其他模块中导入“pet”模块,因为我们可以简单地创建一个“pet”对象并将其作为参数传递给其他类的构造函数。
  3. 使用单例设计模式:我们不必使用单例设计模式,因为我们可以通过创建一个新对象来创建新宠物的实例。

组合模式是一种灵活且强大的设计模式,可用于解决各种问题。它特别适用于需要将对象组合在一起以形成新的对象的情况。