接口隔离原则可以应用于Python对象吗?

时间:2015-10-09 11:50:22

标签: python solid-principles interface-segregation-principle

为了将SOLID原则应用于有机增长且需要重新分解的Python项目,我试图理解 Interface Segregation Principle 的方式当Interfaces不作为语言功能存在时,可以应用于 Python 语言?

2 个答案:

答案 0 :(得分:9)

接口是你可以输入提示的东西,字面上是源代码,或者只是非正式地在文档中。 Python 3支持function annotations,3.5 +实际type hints,即使那些都不存在,您仍然可以在文档中非正式地键入提示。类型提示只是说特定参数应具有特定的特征。

更具体地说:

interface Foo {
    string public function bar();
}

function baz(Foo obj) { .. }

所有这一切都声明,传递给baz的任何参数都应该是一个方法bar的对象,该方法不带参数并返回一个字符串。即使Python没有在语言层面实现任何强制这一点,你仍然可以通过多种方式声明这些东西。

Python确实支持两个重要的事情:abstract classes和多重继承。

而不是interface Foo,在Python中你可以这样做:

import abc

class Foo(abc.ABC):
    @abc.abstractmethod
    def bar() -> str:
        pass

而不是implements Foo,您可以:

class MyClass(Foo):
    def bar() -> str:
        return 'string'

而不是function baz(Foo obj),您可以:

def baz(obj: Foo):
    obj.bar()

由于具有多重继承功能,您可以根据需要精细地隔离接口/抽象类。

Python基于鸭子类型原则,因此它不是通过接口声明和继承来强制执行所有这些,而是​​通常更加松散地定义"参数必须是可迭代的"等等,调用者只需要确保参数 iterable 。抽象类和函数注释与正确的开发工具相结合,可以帮助开发人员在各种执行级别上遵守此类合同。

答案 1 :(得分:0)

保持接口小,并且减少耦合。耦合是指两个软件的连接程度。接口定义的越多,实现类也需要做的越多。这使得该类可重用性降低

我们来看一个简单的例子:


from abc import abstractmethod


class Machine:
    def print(self, document):
        raise NotImplementedError()

    def fax(self, document):
        raise NotImplementedError()

    def scan(self, document):
        raise NotImplementedError()


# ok if you need a multifunction device
class MultiFunctionPrinter(Machine):
    def print(self, document):
        pass

    def fax(self, document):
        pass

    def scan(self, document):
        pass


class OldFashionedPrinter(Machine):
    def print(self, document):
        # ok - print stuff
        pass

    def fax(self, document):
        pass  # do-nothing

    def scan(self, document):
        """Not supported!"""
        raise NotImplementedError('Printer cannot scan!')


class Printer:
    @abstractmethod
    def print(self, document): pass


class Scanner:
    @abstractmethod
    def scan(self, document): pass


# same for Fax, etc.

class MyPrinter(Printer):
    def print(self, document):
        print(document)


class Photocopier(Printer, Scanner):
    def print(self, document):
        print(document)

    def scan(self, document):
        pass  # something meaningful


class MultiFunctionDevice(Printer, Scanner):  # , Fax, etc
    @abstractmethod
    def print(self, document):
        pass

    @abstractmethod
    def scan(self, document):
        pass


class MultiFunctionMachine(MultiFunctionDevice):
    def __init__(self, printer, scanner):
        self.printer = printer
        self.scanner = scanner

    def print(self, document):
        self.printer.print(document)

    def scan(self, document):
        self.scanner.scan(document)


printer = OldFashionedPrinter()
printer.fax(123)  # nothing happens
printer.scan(123)  # oops!