在python中进行“松耦合”的正确方法是什么?

wei*_*ang 4 python loose-coupling python-2.7

我写了一些代码来获取数据pySerial,如下所示。
我的班级依赖于不符合“松散耦合”规则的串行班级。
我应该使用接口来解耦我的类吗?
非常感谢您的指导。

import serial

class ArduinoConnect:  

    def __init__(self):
        pass

    def serial_connect(self, serial_port, serial_baudrate):

        self._serial_port = serial_port
        try:
           self.ser = serial.Serial(
                port=self._serial_port,
                baudrate=serial_baudrate,
                parity=serial.PARITY_NONE,
                stopbits=serial.STOPBITS_ONE,
                bytesize=serial.EIGHTBITS,
            )
        except serial.serialutil.SerialException, e:
            print str(e)

    def serial_disconnect(self):
        self.ser.close()

    def get_quaternion(self, number_of_data=50):

        buff = []
        self.ser.write('q')
        self.ser.write(chr(number_of_data))
        for j in range(number_of_data):
            in_string = self.ser.readline()
            buff_line = in_string.split(",")
            buff_line.pop()
            buff_line = self.hex_to_quaternion(buff_line)
            buff.append(list(buff_line))
        return buff

    def hex_to_quaternion(self, list_of_hex=None):
        #......
        pass

arduino = ArduinoConnect()
arduino.serial_connect(serial_port="COM5", serial_baudrate=115200)
print arduino.get_quaternion()
arduino.serial_disconnect()
Run Code Online (Sandbox Code Playgroud)

我按照建议调整了我的代码。
DI有助于分离串行过程,工厂方法有助于封装DI过程。
我还能做些什么来满足“松散耦合”规则?
谢谢你的帮助。

import serial

class ArduinoConnect:
    def __init__(self, serial_to_arduino):
        self._serial_to_arduino = serial_to_arduino

    def get_quaternion(self, number_of_data=50):
        buff = []
        self._serial_to_arduino.write('q')
        self._serial_to_arduino.write(chr(number_of_data))
        for j in range(number_of_data):
            in_string = self._serial_to_arduino.readline()
            buff_line = in_string.split(",")
            buff_line.pop()
            buff_line = self.hex_to_quaternion(buff_line)
            buff.append(list(buff_line))
        return buff

    def hex_to_quaternion(self, list_of_hex):
        ......

    def __getattr__(self, attr):
        return getattr(self._serial_to_arduino, attr)


class SerialToArduino:
    def __init__(self):
        pass

    def serial_connect(self, serial_port="COM5", serial_baudrate=115200):
        self._serial_port = serial_port
        try:
            self.ser = serial.Serial(
                port=self._serial_port,
                baudrate=serial_baudrate,
                parity=serial.PARITY_NONE,
                stopbits=serial.STOPBITS_ONE,
                bytesize=serial.EIGHTBITS,
            )
        except serial.serialutil.SerialException, e:
            print str(e)

    def serial_disconnect(self):
        self.ser.close()

    def readline(self):
        return self.ser.readline()

    def write(self, data):
        self.ser.write(data=data)


def get_ArduinoConnect():
    'factory method'
    return ArduinoConnect(serial_to_arduino=SerialToArduino())


arduino = get_ArduinoConnect()
arduino.serial_connect(serial_port="COM5", serial_baudrate=115200)
print arduino.get_quaternion()
arduino.serial_disconnect()
Run Code Online (Sandbox Code Playgroud)

Tan*_*yen 5

我能想到 2 种可能的解决方案

  1. 实现一个“适配器”以向主类公开方法并隐藏 Serial 的实现。这样你的主类就可以避免依赖具体的类 Serial
  2. 做依赖注入,像这样

    def serial_connect(self, engine, serial_port, serial_baudrate)

更新 1:我参考了http://en.wikipedia.org/wiki/Adapter_pattern,当您想将具体实现与抽象分离时,通常会使用它。将其视为旅行插头适配器。

它对于像 Java 这样具有严格接口和一切的语言特别有用。在您的情况下,因为在 Python 中我们没有“接口”,您可以使用抽象类来模拟它

class AbstractAdapter():
      def serial_connect(self, serial_port="COM5", serial_baudrate=115200):
          raise("Needs implementation")
      # do the same thing for the rest of the methods
Run Code Online (Sandbox Code Playgroud)

然后在ArduinoConnect,您可以检查类型

def __init__(self, serial_to_arduino):
    if not isinstance(serial_to_arduino, AbstractAdapter):
        raise("Wrong type")
Run Code Online (Sandbox Code Playgroud)

这迫使您serial_to_arduino进行扩展AbstractAdapter,从而强制执行所有抽象方法的实现,因此是适配器。

这可能不是最“pythonic”的做事方式,但从 OOP 的角度来看,你可以这样做以获得最高级别的松散耦合(在我看来)

P/s:实际上,我认为在这种情况下正确的模式应该是 Strategy,它们在实现方面非常相似,但它们用于不同的目的。你可以阅读更多关于一些模式的信息,比如策略、代理、命令、中介,这些模式经常被用来实现松耦合