人人都能读懂的设计模式(2):结构型模式

用最简单的语言,解释设计模式。

虽然示例代码是用 PHP7 实现的,但因为概念是一样的,所以语言并不会阻碍大家理解设计模式。

人人都能读懂的设计模式(1):创建型模式

结构型设计模式

概述

结构型设计模式主要关注对象组合,换句话说,关注实体之间如何互相使用。 或者还有另外一个解释,结构型设计模式有助于回答“如何构建软件组件?”

维基百科

在软件工程中,结构型设计模式是借由一以贯之的方式来了解元件间的关系,从而简化设计的一种设计模式。

分类

  • 适配器模式
  • 桥接模式
  • 组合模式
  • 修饰模式
  • 外观模式
  • 享元模式
  • 代理模式

🔌 适配器模式

现实生活示例

考虑这样一个场景,你的存储卡中有一些照片,你需要将其传输到计算机。为此,你需要某种与计算机端口兼容的适配器,以便将存储卡连接到计算机上。在这种情况下,读卡器就是适配器。另外一个例子就是大名鼎鼎的电源适配器:一个三脚插头不能连接到双插头插座,需要使用电源适配器使其与双插头插座兼容。另外一个例子是译者将一个人说的话翻译给另一个人。

概述

适配器模式可以将不兼容的对象包装成适配器来适配其它类。

维基百科

在软件工程中,适配器模式是允许将现有类的接口用作另一个类接口的软件设计模式。它通常用于现有类与其他类的协作,而无需修改现有类的代码。

程序示例

考虑一个游戏场景,有一个猎人,他狩猎狮子。

首先给出 Lion 接口,所有种类的狮子都要实现这个接口。

猎人希望可以狩猎任何实现 Lion 接口的狮子

现在我们假定猎人在游戏中也可以狩猎野狗。但是目前我们无法实现,因为狗是通过其他接口实现。为了让猎人可以狩猎野狗,我们需要创建一个适配器,来兼容这种情况。

这样,在游戏中通过 WildDogAdapter 就可以使用 WildDog

🚡 桥接模式

现实生活示例

假如你有一个网站,上面有不同的网页,并且允许用户更改主题。你会如何实现呢?是为每个页面的各个主题创建多个副本,还是创建单独的主题,并根据用户的偏好来加载主题呢?桥接模式可以帮你实现后者。

不使用桥接模式

2 1

使用桥接模式

2

概述

桥接模式主打的是组合优于继承。实现细节从对象的层次结构推送给具有单独层次结构的另一个对象。

维基百科

桥接模式是软件工程中使用的设计模式,旨在“将抽象与实现分离,使得两者可以独立变化”

程序示例

以上面提到的网页为例,下面是 WebPage 的结构

独立的 主题 结构

都是两层结构

🌿 组合模式

现实生活示例

每个公司都是由员工组成,每个员工都有一些共同特征比如薪资以及所承担的某些责任,会或者不会向其他人汇报工作,有或者没有下属等。

概述

组合模式让客户端以统一的方式对待各个对象。

维基百科

在软件工程中,组合模式是一种分治设计模式。组合模式对待一组对象的处理方式与对待对象的单个实例相同。组合的意图是将对象“组合”成树状结构以呈现部分-整体的层次结构。实现组合模式可以使客户端能够均匀地处理单个对象和组合。

程序示例

以上面提到的员工为例,下面是不同的员工类型

包含几种不同类型员工的公司

然后可以这样调用

☕ 装饰器模式

现实生活示例

想象一下,你在经营一家提供多种服务的汽车服务站。现在如何计算收费帐单呢?选择一项服务,并动态地向其添加价格,直到获得最终成本。这里每种类型的服务就是装饰器。

概述

通过将对象包装在装饰器类的对象中,装饰器模式可以在运行时动态地更改对象的行为。

维基百科

装饰器模式,是面向对象编程领域中,一种动态地或静态地往一个类中添加新行为而不影响相同类中其他对象的设计模式。装饰器模式对于遵守单一责任原则通常是有用的,因为它允许在具有独特领域的类之间划分功能。

程序示例

我们以咖啡为例,首先我们通过咖啡接口实现一个简单咖啡

我们希望代码可扩展,以允许选项在需要时进行修改。 增加一些附加项(装饰器)

下面我们来做杯咖啡吧

📦 外观模式

现实生活示例

请问你会如何打开计算机呢?你会回答:“按电源键就行!”。你会这样想是因为你在使用计算机对外提供的简易接口,但是在内部,计算机完成了很多工作后才得以启动,这种复杂子系统的简单接口就是外观模式。

概述

外观模式提供了一个简化复杂系统的简单接口。

维基百科

外观模式是指针对像类库这种大体积代码提供简化接口的对象。

程序示例

以上面提到的计算机为例,给出计算机类

下面是计算机的外观

可以这样使用外观模式

🍃 享元模式

现实生活示例

你是否在某个摊位上喝过茶?店主总是会多做一些茶,以预留给其他顾客,以此来节省资源比如燃气。享元模式所讲的就是共享。

概述

享元模式通过相似对象之间尽可能的资源共享,来最小化内存使用或计算开销。

维基百科

在计算机编程中,享元模式是一种软件设计模式。享元模式是通过与其他类似对象共享尽可能多的数据来最小化内存使用的对象; 当简单的重复对象过多占用内存时,可以通过享元模式来处理大量相似对象的情况。

程序示例

以茶为例,首先定义茶的种类及茶具

然后定义茶店来接单及提供服务

下面可以这样使用

🎱 代理模式

现实生活示例

有没有过使用门禁卡进门的经历呢?打开门的方法有多种,既可以使用门禁卡,也可以按下门上的安全按钮。门的主要功能是打开,但在其上添加一个代理,便可以给门添加一些功能。下面的代码示例可以给出更好的解释。

概述

使用代理模式,一个类可以代理另外一个类的功能。

维基百科

一个代理,其最一般的形式,是一个作为其他类接口的类。代理是由客户端调用的包装器或代理对象,用来访问幕后的真实服务对象。使用代理可以简单地向真实对象做转发,或者可以提供额外的逻辑。在代理模式中,可以提供额外的功能,例如当在真实对象上的操作是资源密集型时进行缓存,或者在调用真实对象的操作之前进行预处理。

程序示例

以安全门为例,首先给出安全门接口及实现

然后使用代理来确保门的安全

可以这样使用

另一个例子是实现某种数据映射器。例如,我最近使用这种模式为 MongoDB 做了一个 ODM(对象数据映射器),其中我使用魔术方法__call() 在 mongo 类上编写代理。所有的方法调用被代理到原始的 mongo 类,并且检索的结果原样返回,但如果调用 findfindOne ,数据会被映射到所需的类对象,并且返回了对象而不是Cursor

打赏支持我翻译更多好文章,谢谢!

打赏译者

打赏支持我翻译更多好文章,谢谢!

1 4 收藏 1 评论

关于作者:Justin(李加庆)

Python工程师一枚,对go、docker感兴趣,还在成长ing~~ 个人主页 · 我的文章 · 15

相关文章

可能感兴趣的话题



直接登录
最新评论
跳到底部
返回顶部