【问题标题】:Passing objects to other objects - via methods or constructor?将对象传递给其他对象 - 通过方法或构造函数?
【发布时间】:2012-04-06 00:24:05
【问题描述】:

情况是这样的。我有以下伪类:

class Agent:
    def __init__(self):
       self.blah = whatever
       self.boo = thingy

    def doA(self, transport):
       res = transport.doX(self.blah)

    def doB(self, transport):
       res = transport.doY(self.boo)

class Transport:
    def __init__(self):
        self.bah = weee

    def doX(self, item):
        #.. do some other stuff here

    def doY(self, item):
        #.. do some more stuff here

现在,我的问题是 - 我应该将我的传输对象传递给需要它的方法的代理方法,还是应该简单地将传输对象传递给代理构造函数并从方法中调用它?即

transport = Transport()
agent = Agent(transport)
class Agent:
    def __init__(self, transport):
        self.blah = whatever
        self.transport = transport

    def doA(self):
        res = self.transport.doX(self.blah)

我将 Transport 移到它自己的班级的原因是:

1) 代理实例可以共享相同的传输对象 - 即:我只需要一个传输对象用于一组代理。我可以有多个传输(一个用于agentA..N,另一个用于agentO..Z)。

2) 传输包含将代理列表作为参数的方法。例如,它可以在给定代理对象列表的情况下对代理运行并发通信测试。

但是,代理本身有时需要在传输中设置的属性(SSL 证书的位置等),以便在代理类中使用一些有意义的方法(远程重新启动代理等)。

我是否应该采用需要代理列表的方法并将它们移动为 Transport 的类方法,然后在包含 Transport 实例的 Agent 对象中创建一个属性?我是否应该继续我正在做的事情,只需要将 Transport 对象传递给某些 Agent 对象方法?我应该以我没有看到的某种方式重构这一切吗?

任何有用的意见将不胜感激。

【问题讨论】:

  • 听起来你要打破另一层耦合。
  • 1) 同一个代理会与几种不同的传输方式一起工作吗? 2)代理可以在任何传输连接到它之前做一些有用的事情吗? 3)在任何代理连接到它之前,传输可以做一些有用的事情吗?
  • Ignacio,我同意 - 但我问这个是因为我不确定如何将它们解耦。

标签: python oop class theory


【解决方案1】:

由于您甚至考虑将传输作为参数添加到代理的构造函数,我假设一个代理永远不会与多个传输一起使用。

我假设一个传输实例可以在没有任何代理连接的情况下做一些有用的事情,反之亦然。

如果我的假设是正确的,我会提出这个建议:

class System:
  def associate_transport_and_agent(transport, *agents):
    for agent in agents:
      transport.add_agents(*agents)
      agent.set_transport(transport)

class Transport:
  def __init__(self):
    self.bah = weee
    self.agents = set()
  def add_agents(self, *agents):
    self.agents.update(agents)
  def remove_agent(self, agent):
    self.agents.remove(agent)
  def doX(self, item):
    # ...


class Agent:
  def __init__(self):
    self.blah = whatever
    self.transport = None
  def set_transport(self, transport):
    if self.transport == transport:
      return
    if self.transport is not None:
      self.transport.remove_agent(self)
    self.transport = transport

  def doA(self):
    res = self.transport.doX(self.blah)

如果您打算删除对象,您可能需要通过使用从代理到传输或其他方向的弱引用来帮助垃圾收集器(或者实际上,在您的情况下,在两个方向上,因为您可能包含强引用在别处发给他们)。

编辑:

已更新以反映代理可能会更改其传输方式:

  • 将代理列表更改为代理集
  • 添加了 Transport.remove_agent
  • 修改了 Agent.set_transport 以检查之前是否已经设置了一个

【讨论】:

  • 代理只能使用 1 个传输,尽管可以切换该传输。因为这实际上只是一个更大的服务器/客户端架构的 API,我会说不。我必须使用传输与代理进行通信才能做任何有用的事情。我将传输器移出的唯一原因是同时跨多个代理运行的方法。将这种逻辑保留在代理中似乎确实是错误的想法(即,在一个代理中使用一种方法来影响自己和其他代理)。我会试试你上面发布的东西。
【解决方案2】:

鉴于“代理只能使用 1 个传输,尽管可以切换该传输”,我建议您为 __init__ 设置一个(可选)参数来设置传输,并使用代理的传输属性公开。如果您需要在赋值时运行代码,请创建一个属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 2013-11-13
    • 2014-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多