0

场景如下:

我正在构建一个将外部脚本用作插件的框架。人们将能够为符合某些接口的脚本创建“适配器”。这些适配器将被集成到框架中(因此需要插件注册)或通过简单的导入“松散地”使用。

换句话说,适配器用于脚本使用标准化。

我可能想得太复杂了,但我目前正在使用的解决方案涉及创建一个定义接口(和一些实用方法)的抽象类。抽象类的模块将只加载一次,框架将加载一个带有自注册元类的版本,而插件本身将加载一个更简单的版本(第一个注册抽象类的版本获胜)。

这迫使插件有一个定义抽象类的文件,因此是“合同”。我看不出有什么问题。

我不会真的有两个不同的抽象类,而是一个模块文件中的一个,它的行为取决于它的加载位置(框架或插件本身)。但这不应该是相关的(我认为)。

这就是抽象类/元类的样子

#imp/plugin.py
import abc
class PluginAbstract(object):
    class __metaclass__(abc.ABCMeta):
        def __init__(self, name, bases, namespace):
            if name != 'PluginAbstract':
                pass #We can register the new "sub-class" if required
            return abc.ABCMeta.__init__(abc.ABCMeta, name, bases, namespace)

实现将类似于:

#impl/MyPlugin.py
if 'plugin' not in locals():
    from impl import plugin

class MyPlugin(plugin.PluginAbstract):
    pass  #rest of the implementation....

因此,如果框架已经注册PluginAbstract,则将继承该框架,否则将使用合同文件中的那个。 impl/plugin.py

我不希望适配器需要安装框架,因此需要安装带有接口的单个​​文件。

这个策略有意义吗?还有其他选择吗?

4

1 回答 1

1

在 Python 中,“强制”一个接口是不寻常的。我们通常使用鸭式打字,这是通过合同或其他“束缚和纪律”方法进行设计的常识性替代方案。Duck-typing 的意思是,如果它像鸭子一样走路,像鸭子一样嘎嘎叫,那它一定是鸭子。

实际上,这意味着您根本不强制执行静态类型。相反,您相信使用正确的文档,您的代码的用户会简单地做正确的事情。这通常会大大简化您的代码。它还会让你专注于真正重要的事情,比如检查有效的输入数据。

对于具有静态类型背景(例如 Java 或 C++)的人来说,duck-typing 通常会引起某种存在主义焦虑,例如看着深渊,发现深渊回望过去。放手吧。没有深渊,只有在你的脑海里。

于 2012-11-21T10:49:50.653 回答