我正在编写一个Python程序,它将使用Twisted连接到TCP服务器。套接字另一端的服务器可能正在运行两种可能的协议之一(protoA或protoB),但在我启动连接并“询问”服务器正在使用哪种协议之前,我不会知道它是哪一种。用过的。我能够在连接后识别出正在使用的协议版本(protoA或protoB),但我不提前知道。
显然,一个解决方案是在我的扭曲的协议派生类中有很多特殊情况代码 - 即如果protoA这样做,那么elif protoB会做其他事情。但是,我希望能够在两个单独的协议实现中保留两个单独协议的代码(尽管它们可能通过基类共享一些功能)。由于协议的两个版本都涉及维护状态,因此将两个版本混合到同一个类中会很快变得混乱。
我该怎么做?有没有办法在Factory实现中进行初始的“协议识别”步骤,然后实例化正确的协议衍生物?
答案 0 :(得分:4)
不要在整个协议实施过程中混合使用决策逻辑,而是将其放在一个地方。
class DecisionProtocol(Protocol):
def connectionMade(self):
self.state = "undecided"
def makeProgressTowardsDecision(self, bytes):
# Do some stuff, eventually return ProtoA() or ProtoB()
def dataReceived(self, bytes):
if self.state == "undecided":
proto, extra = self.makeProgressTowardsDecision(bytes)
if proto is not None:
self.state = "decided"
self.decidedOnProtocol = proto
self.decidedOnProtocol.makeConnection(self.transport)
if extra:
self.decidedOnProtocol.dataReceived(extra)
else:
self.decidedOnProtocol.dataReceived(bytes)
def connectionLost(self, reason):
if self.state == "decided":
self.decidedOnProtocol.connectionLost(reason)
最终你可以用更少的样板来实现它:http://tm.tl/3204/
答案 1 :(得分:1)
这很容易用一些魔法完成。
class MagicProtocol(Protocol):
...
def dataReceived(self, data):
protocol = self.decideProtocol(data)
for attr in dir(protocol):
setattr(self, attr, getattr(protocol, attr))
这很难看,但它会有效地为选择的协议切换Magic协议。