【问题标题】:Advantages to two modules with same interface or two classes with the same interface?具有相同接口的两个模块或具有相同接口的两个类的优点?
【发布时间】:2016-01-06 13:54:56
【问题描述】:

例如,我可以创建两个具有f() 的模块(Mod1Mod2)。或者我可以创建两个实现f() 的类。

那我也可以

if condition:
    import Mod1 as m
else:
    import Mod2 as m

m.f()

if condition:
    m = Class1()
else:
    m = Class2()
m.f()

显然,如果我想存储我需要使用类的任何状态,但如果我只是使用类方法,那么任何一种方法都比另一种方法有优势吗?

编辑:我最关心的是可维护性/可扩展性/可读性,而不是运行时性能。

【问题讨论】:

  • 我认为这取决于您使用 f() 的频率/用途
  • 在这种特殊情况下,我可能只会调用每个方法一次,但我也对一般情况感到好奇。
  • 我认为一般来说,你会创建模块,而不是类,因为一个类通常与创建具有属性、类方法等的对象实例相关联,而不仅仅是函数。

标签: python oop module ooad


【解决方案1】:

总体思路

在您的具体情况下,您可以使用简单的模块级功能,而不是让一切过于复杂。但是,如果您对一般情况感兴趣,我建议您使用Abstract Factory pattern。这是一个示例解决方案:

class YourAbstractFactory(object):
    @classmethod
    def get_factory(cls, condition):
        cond_map = {
            'impl1': Impl1,
            'impl2': Impl2
        }

        impl = cond_map.get(condition)

        return impl() if impl else None

    def f1(self):
        pass

    def f2(self):
        pass

YourAbstractFacotry 类显然是一个抽象类,它只是定义了要实现的接口,即f 函数的集合。此外,它定义并实现了get_factory 类方法,该方法根据条件返回适当的实现。

class Impl1(YourAbstractFactory):
    def f1(self):
        print('Impl1.f1')

    def f2(self):
        print('Impl1.f2')

class Impl2(YourAbstractFactory):
    def f1(self):
        print('Impl2.f1')

    def f2(self):
        print('Impl2.f2')

以上类是你的接口的两个独立实现。它们彼此不知道,可以独立存在。

# This is where you put your condition, and get appropriate instance
>>> impl = YourAbstractFactory.get_factory('impl2')
>>> impl.f1()
Impl2.f1

因此,在一般情况下,此解决方案的优势在于您的客户端代码将与您的实现分离。这意味着,您只会通过条件并获得所需的实现,并且对客户端代码中的实现没有任何想法和依赖。唯一知道接口具体实现的是get_factory方法,它很容易维护。

其他改进

为了进一步增强此解决方案并提高安全性(尽管 Python 是一种成人语言;)),您还可以使用 abc 模块及其 ABCMeta 元类和 abstractmethod 装饰器,以防止初始化没有实现所有接口的类的实例。在这种情况下,您需要像这样定义您的工厂类。

from abc import ABCMeta, abstractmethod

class YourAbstractFactory(object):
    __metaclass__ = ABCMeta

    @classmethod
    def get_factory(cls, condition):
        cond_map = {
            'impl1': Impl1,
            'impl2': Impl2
        }

        impl = cond_map.get(condition)

        return impl() if impl else None

    @abstractmethod
    def f1(self):
        pass

    @abstractmethod
    def f2(self):
        pass

【讨论】:

    猜你喜欢
    • 2022-01-13
    • 1970-01-01
    • 2012-08-22
    • 2020-12-09
    • 1970-01-01
    • 2011-11-30
    • 2013-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多