0
点赞
收藏
分享

微信扫一扫

python 结构型模式

结构型模式在大型应用中非常重要。它们决定代码的组织方式,并告诉开发人员如何

与应用程序的每个部分进行交互。

很长一段时间以来,在 Python 中,Zope 项目中的 Zope 组件架构(Zope Component

Architecture,ZCA)提供了最知名的许多结构型模式的实现。它实现了本节中描述的大多 数模式,并提供了一组丰富的工具来处理它们。ZCA 不仅可以在 Zope 框架中运行,而且 也可以在其他框架(如 Twisted)中运行。它提供了接口和适配器的实现。

不幸的是(或许不是),Zope 失去了几乎所有的势头,并不如以前那样流行。但是它的 ZCA 可能仍然是在 Python 中实现结构型模式很好的参考。Baiju Muthukadan 创建了 Zope 组件 架构的综合指南(A Comprehensive Guide to Zope Component Architecture)。可以免费地打印或 者在线阅读它(参见 http://muthukadan.net/docs/zca.html)。该书写于 2009 年,所以它没有涵盖 Python 的最新版本,但它仍然是一份很好的资料,因为它提供了很多上述模式的基本原理。

Python 已经通过其语法提供了一些流行的结构型模式。例如,类和函数装饰器可以被 认为是装饰器模式(decorator pattern)的应用。此外,支持创建和导入模块是模块模式

(module pattern)的一种发散。

常见的结构模式有很多。最初的设计模式(Design Patterns)书中描述了 7 种,并且后

续其他文献扩展也对这些模式进行了扩展。我们不会讨论所有的模式,主要关注 3 个最受 欢迎并且公认的模式,它们是:

• 适配器(adapter); • 代理(proxy);

• 外观(facade)。

使用适配器(adapter)模式可以在另一个接口中使用现有类的接口。换句话说,适配器包 装一个类或一个对象 A,以便它能在目标上下文中工作,这可以是一个类或者一个对象 B。

在 Python 中创建适配器实际上是非常简单的,这归应于这种语言中的类型工作原理。 Python 中的类型原理通常被称为鸭子类型(duck-typing):

“如果它走路像鸭子,说话像鸭子,那就它就是鸭子!”

根据这个规则,函数或方法接受的值,不应该取决于它的类型,而应基于其接口。所 以,只要对象的行为正如预期的那样,即具有适当的方法签名和属性,它的类型被认为是 兼容的。这与许多静态类型语言是完全不同的,在这些语言里这种事情几乎是不可行的。

实际上,当某些代码用于处理给定的类时,只要它们提供了代码使用的方法和属性, 就可以向它提供来自另一个类的对象。当然,这假设代码不会调用 instance 来验证实例 是否是特定类的实例。

适配器模式基于这个原理,并定义了一个包装机制,其中包装类或对象,以使其在主 要不是为它工作的上下文中工作。StringIO 是一个典型的例子,虽然它适配 str 类型, 同样它可以作为 file 类型如下所示:

>>> from io import StringIO

>>> my_file = StringIO('some content') >>> my_file.read()

'some content'

>>> my_file.seek(0)

>>> my_file.read(1) 's'

让我们举另一个例子。DublinCoreInfos 类显示给定文档的都柏林核心集(Dublin Core)信息的一些子集的摘要(参见 http://dublincore.org/),该信息由一个 dict 提供。它读 取几个字段,如作者的姓名或标题,并打印它们。为了能够显示文件的都柏林核心集,必须 以 StringIO 同样的方式进行修改。图 14-1 显示了这种类型的适配器模式实现的 UML 图。

图 14-1 简单适配器模式示例的 UML 图 DublinCoreAdapter 包装一个文件实例,并通过它提供元数据访问如下所示:

      from os.path import split, splitext

class DublinCoreAdapter:

def __init__(self, filename):

self._filename = filename

          @property

          def title(self):

return splitext(split(self._filename)[-1])[0]

          @property

          def languages(self):

              return ('en',)

def __getitem__(self, item):

return getattr(self, item, 'Unknown')

    class DublinCoreInfo(object):

def summary(self, dc_dict):

print('Title: %s' % dc_dict['title'])

print('Creator: %s' % dc_dict['creator']) print('Languages: %s' % ', '.join(dc_dict['languages']))

以下是使用示例:

   >>> adapted = DublinCoreAdapter('example.txt')

   >>> infos = DublinCoreInfo()

   >>> infos.summary(adapted)

   Title: example

   Creator: Unknown

   Languages: en

除此之外它允许替换,适配器模式也可以改变开发人员的工作方式。使对象在特定上 下文中工作使得假设对象的类不再重要。重要的是,这个类实现了 DublinCoreInfo 正 在等待的行为,这个行为是由适配器修复或完成的。因此,代码可以,只是设法,告诉它 是否与实现特定行为的对象兼容。这可以由接口表示。

举报

相关推荐

0 条评论