繁体   English   中英

Python Borg多重继承和共享状态

[英]Python Borg Multiple Inheritance and Shared State

我在一个有趣的项目中遇到了这个问题,在这个项目中,我必须告诉类在指定的开始时间和结束时间(以及间隔c)下在特定时间段内执行操作。

为了便于讨论,请考虑类A(具有我调用的API的类)必须调用类B(它调用C类,然后又调用D类)和E(又调用F类和G类)。 )。

A-> B-> C-> D

A-> E-> G

现在,BC和E类需要有关时间的上下文。 我目前已对其进行设置,以使A类将上下文传递给B和E类,然后它们又根据需要传递上下文。

我正在尝试找出解决此要求的最佳方法,而又不会传递上下文,而且我非常讨厌它,我正在考虑使用Highlander(或Singleton)或Borg模式(Monostate的变体)。 我只是想知道我对这些模式有什么选择。

选项1

使用传统的博格,例如:

class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state

我可以在任何地方简单地实例化此类,并可以访问所需的全局状态。

选项2

单态的另一个变体:

class InheritableBorg:
    __time = (start, end, interval)
    def __init__(self):
        pass

    @property
    def time(self):
        return __time

    @time.setter
    def time(self, time):
        __time = time

从理论上讲,这将允许我简单地通过以下方式进行扩展:

class X(InheritableBorg):
    pass

并扩大我只会做:

class NewInheritableBorg(InheritableBorg):
    __time = (0, 0, 'd')

那么从理论上讲,我可以利用多重继承,然后便可以一次性访问多个博格,例如:

class X(InheritableBorg1, InheritableBorg2):
    pass

我什至可以有选择地覆盖东西。

选项3

如果可能,使用包装的嵌套函数作为类装饰器/包装器。 但是,我只能使用一次,并且需要传递函数句柄。 这是基于代理/委托思想的混合。

这在我脑海中并不具体,但本质上类似于:

def timer(time)
    def class_wrapper(class_to_wrap):

        class Wrapper(class_to_wrap):
            def __init__(self, *a, **kw):
               super().__init__(*a, **kw)
            def get_time(self):
               return time
        return Wrapper
    return class_wrapper

@timer(time)
class A_that_needs_time_information:
    pass

I think that might work... BUT I still need to pass the function handle.

摘要

所有这些都是可能的解决方案,而我倾向于多重继承Borg模式(尽管类包装器很酷)。

  1. 常规的Borg模式必须被实例化太多次,以至于仅存储一组值似乎开销太大。

  2. Borg mixin实例化的次数与类实例化的次数相同。 我不知道如何进行测试。

  3. 包装器是超通用的,并且相对容易测试。 从理论上讲,因为它是一个函数闭包,所以我应该能够对东西进行突变,但是从本质上来说,它变成了一个单例(这似乎太复杂了,在这种情况下,我也可能只使用常规的单例模式)。 同样,传递函数句柄会破坏目标。

除以上三种方法外,还有其他方法可以这样做吗? 还有更好的方法吗(因为没有DI,Borg似乎很难测试)? 我似乎错过了任何缺点吗?

另外,我也可以坚持现在的样子……按照需要打发时间。 它满足了松散的耦合要求和DI最佳实践……但又太麻烦了。 一定有更好的方法!

作为一般经验法则,请尝试使事情保持简单。 您正在考虑针对一个相对简单的问题的非常复杂的解决方案。

有了您提供的信息,您似乎可以将执行操作的请求包装在也包含上下文的对象中。 然后,您只需在不同类之间传递一个对象。 例如:

class OperationRequestContext:
    def __init__(self, start_time, end_time):
        self.start_time = start_time
        self.end_time = end_time

class OperationRequest:
    def __init__(self, operation, context):
        self.operation = operation
        self.context = context

如果有其他要求可以考虑使用更复杂的解决方案,则应指定它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM