结构型模式

结构型模式用来组装 类和对象,以获得更大的结构。

结构型类模式,通过继承机制来组合接口或类。简单的例子就是多重继承,最后一个类拥有所有父类的性质。这个模式有助于独立开发一个协同类。另一个例子是类型是的 Adapter 模式,它通过私有继承待适配接口(C++),生成一个多接口的抽象,这个抽象就可以被当做待适配接口的占位符。

结构型对象模式不是对接口和类进行组合,而是对对象进行组合。从而可以动态改变组合,得出新功能。因此更加灵活。结构型对象模式常见有如下几种:

  1. Composite模式。构造一个类层次结构,这个层次结构中有两种类,一种是基元类,一种是组合类。其中组合类可以组合基元类和组合类,从而可以构造出很复杂结构。
  2. Proxy模式。Proxy对象用作其他对象的占位符,因此可以对被代理对象的请求做一些额外的操作,比如安全检查。同时也可以增减,限制,修改被代理对象提供的功能。
  3. Flyweight模式。创建可以共享的没有状态的对象。
  4. Facade模式。创建单个对象,以表示整个系统。(这个对象会将请求转发给所表示的对象)
  5. Bridge模式。该模式分离对象的抽象和实现,这样两边都可以演化。
  6. Decorator模式。该模式用于动态给对象增加功能。

这部分我们使用跟创建型模式一样的例子。即一个迷宫游戏。这个游戏的组件有:

  • Maze – 迷宫,由多个房间组成
  • Room – 房间,有 东南西北 四个方向,每个方向要么是墙壁,要么是门
  • Door – 门,组成房间
  • Wall – 墙壁,组成房间

这些是抽象类,迷宫有两种实现,一种是正常的迷宫,即门使用钥匙打开,墙壁是水泥墙壁。另一种是魔法迷宫,门是魔法门,使用咒语打开,墙壁是魔法墙壁。

1. Adapter

Adapter 模式是使用一个已有的类或对象来实现我们的接口。

比如上面的例子,假设正常迷宫的组件已经实现好了,现在要实现魔法迷宫。需要实现一个魔法墙,这个墙壁可以使用法杖打开。我们知道正常迷宫的门是可以使用钥匙打开的。所以我们不想再实现,想要套用正常迷宫的门对象,然后给它传递一个特殊的钥匙(法杖)就来打开墙壁(切换到另一个房间)。

这时候合适使用 Adapter 模式,即使用【正常门】实现【魔法墙】。其中【正常门】称为 Adaptee,【魔法墙】称为 Adapter。

Adapter 有两种形式,一种使用继承(基于类),另一种使用组合(基于对象)。他们的结构分别如下所示:

  1. Adapter类模式结构(使用继承)

  1. Adapter 对象模式(使用组合)

2. Bridge

Bridge 用来分离抽象和实现。

举个例子:用上面的例子,我们的迷宫游戏中有墙,墙的实现有两种 一般墙 和 魔法墙。假如现在我们还要求有的需要显示一些文字来作为迷宫的线索。那么就会多出两中墙,空白墙 和 文字墙。

如果我们使用原先抽象和实现来实现,我们需要实现四个类,NormalBlankWall,NormalTextWall,MagicBlankWall,MagicTextWall ,我们的结构图如下所示:

但是,如果使用 Bridge 模式,我们可以将 Wall 的抽象 和 实现分开,这样抽象和实现可单独演化。使用 Bridge 模式的结构图如下所示:

上面的 Wall 和 WallImplementor 的关系称为桥接。(其实就是一个引用)

3.Composite模式

Composite模式用来构建树形结构。以使应用以同样的方式对待 叶子节点 和 非叶子节点。

还用迷宫游戏做例子,假设现在我们的迷宫组件可以爆炸,它们的 Door/Wall/Room 可以通过特定的方式炸掉。被 Wall/Door 被炸掉后,就可以进入到对面房间。Room被炸掉后,就可以进入四个方向的任意房间。这时候,就可以使用 Composite 模式了。

首先,我们需要构造一个抽象的 BombComponent。这个接口声明一个 bomb 方法。BombDoor / BombWall / BombRoom 通过实现这个 bomb 方法来完成爆炸。但是这个 BombComponent 除了声明 bomb 方法。它还声明了 add, remove,getChild 方法。后面这三个方法就是 BombComponent 之所以称为 Composite 模式的原因。

BombDoor / BombWall 分别实现 BombComponent 的 bomb 方法来销毁它们即可。但是 BombRoom 需要除了需要在 bomb 方法中销毁自己以外,它还需要销毁四个方向的 BombDoor, BombWall 等子组件。下面是它们的结构图:

上面的 BombWall 和 BombDoor 是叶子节点,add, remove, getChild 方法只需要一个默认什么也不做的实现即可。但是 BombRoom 是组合节点。需要实现这些方法。并使用一个实例变量 list 来存储它的子组件。(子组件既可以是叶子节点,也可以是组合节点)。我们说上面 BombRoom 实现了 Composite 模式。

4.Decorator

Decorator模式用来动态增加对象的功能。相比继承来增加功能, Decorator更加灵活一些。

上面使用 Bridge 模式来新增一个带有文本的墙壁。这是新增了一类墙壁。可以使用文本墙,也可以使用普通墙。但是如果我们仅仅想对某一些构建好的普通墙壁动态涂上文本,对另一些构建好的墙壁涂上图片等。这个时候可以使用 Decorator 模式。这样在需要显示文字的时候,给它装饰 Decorator 就可以了。

Decorator模式的结构图如下所示:

这里需要注意的是,Decorator类需要一个实现 Wall 接口的同时,持有一个 Wall 接口实例(这个实例可以是Decorator子类)。

Decorator 实现 Wall 接口是为了让 Decorator 和 Wall 实现类完全一样。Wall实现类能出现的地方,Decorator都能出现。

Decorator 持有 Wall 实例的原因是:使用这个 Wall 实例来实现 Wall 接口。然后 Decorator 子类在此基础上在扩展,就可以给持有的 Wall 实例增强功能了。

5.Facade

Facade模式用来给一个系统提供一个统一的接口。

我们的迷宫游戏不合适Facade模式,因为迷宫游戏不是一个系统,不向外提供接口。但是有很多系统很复杂,它们向外提供很多接口,通过这些接口来使用系统功能。调用不同的接口组合实现不同的功能。

有时候,系统提供的接口过于细节。很多实用系统的人都不需要全部的自定义能力。这时候,可以提供一个Facade类,这个类整合系统所有接口,向外提供一个默认功能。绝大部分人通过Facade使用系统就可以了。

这样普通开发人员使用Facade,需要对系统有特殊需求的人员也可以直接调用系统提供的接口。

Facade模式的结构如下所示:

如果使用系统的默认方式不止一种,也可以提供一个 Facade 抽象类,每个 Facade 子类,再提供具体使用系统流程。

6.Flyweight

享元模式。这个模式是用来共享对象的。

假如,迷宫游戏的迷宫很大。这样就会需要很多房间,每个房间至少2面墙壁/门。这样当房间的数量很多的时候,应用就需要实例化大量的门/墙对象。因此我们可以使用享元模式来实现它们。前后的结构变化示意图如下:

这样,整个应用的墙/门,就都只有两个实例了。然后门/墙的状态信息保存在房间中。比如有的前是文字墙,有的墙是图片墙。当房间在构建时,它传递这个状态给墙/门,然后墙/门再根据状态生成它们自己。

下面是 Flyweight 模式的结构示意图:

从上图可以看到,Flyweight 除了有共享的对象,还有不共享的对象。注意 Flyweight 接口中应该还维持一个状态,通过这个状态配置每个共享对象。

7.Proxy

Proxy 模式是用来给一些对象做占位符的。常用的被占位的对象有如下3中:

  1. 大对象 – 加载需要很长时间,使用代理模式先占位,真正需要用到目标对象再加载。这种代理模式叫 虚代理(virtual proxy)
  2. 远程对象 – 在不同进程空间的对象,通过代理操作远程对象。这种代理模式叫 远程代理(remote proxy)
  3. 重要对象 – 需要进行安全保护的对象,限制对目标对象的某些操作。这种代理模式叫 保护代理(protection proxy)

总之,Proxy 模式用来占位,然后在合适的时候将请求发送到真正对象。

这里通过上面迷宫游戏,举例一个 虚代理。

之前我们使用 Decorator 来给 Wall 画上图片。现在我们当这种 Decorator Wall 是一种 Wall 实现,叫 ImageWall。现在假设图片都在硬盘上,当迷宫很大,而且有很多的 ImageWall 时,若在玩家开始游戏时就构建整个迷宫的 ImageWall,那较长的时间去操作硬盘。这时候可以使用 Proxy 模式。ProxyWall 先用来占个位,把迷宫构建起来,当玩家真正进入到房间需要一个 ImageWall 的时候,ProxyWall 再从磁盘中读取图片,构建ImageWall,之后所有对 ProxyWall 的操作,都转到新建的 ImageWall 上。

下图是 Proxy 模式的结构图:

这个模式比较简单,但是要注意如下两点:

  1. 它跟 Adapter 模式差异:Adapter 模式是适配两个接口,这里没有适配其他接口
  2. 它跟 Decorator 模式差异:Decorator 模式是为了增加功能,但是这里没有增加功能。其次 Decorator 模式一直持有被装饰对象,但是 Proxy 模式不一定持有(远程代理)。最后,不像 Decorator,Proxy 没有递归引用(其实有时也有,这样 Proxy 就引用一个抽象接口。但虚代理最后要实例化被代理类,所以虚代理需要知道这个最终类)。

8.结构型模式汇总

结构型模式是为了构建大对象。结构型模式分为类模式 和 对象模式,类模式是静态的 而 对象模式是动态的,因此对象模式更加灵活。下面复制第一部分内容用于回顾:

结构型类模式,通过继承机制来组合接口或类。简单的例子就是多重继承,最后一个类拥有所有父类的性质。这个模式有助于独立开发一个协同类。另一个例子是类型是的 Adapter 模式,它通过私有继承待适配接口(C++),生成一个多接口的抽象,这个抽象就可以被当做待适配接口的占位符。

结构型对象模式不是对接口和类进行组合,而是对对象进行组合。从而可以动态改变组合,得出新功能。因此更加灵活。结构型对象模式常见有如下几种:

  1. Composite模式。构造一个类层次结构,这个层次结构中有两种类,一种是基元类,一种是组合类。其中组合类可以组合基元类和组合类,从而可以构造出很复杂结构。
  2. Proxy模式。Proxy对象用作其他对象的占位符,因此可以对被代理对象的请求做一些额外的操作,比如安全检查。同时也可以增减,限制,修改被代理对象提供的功能。
  3. Flyweight模式。创建可以共享的没有状态的对象。
  4. Facade模式。创建单个对象,以表示整个系统。(这个对象会将请求转发给所表示的对象)
  5. Bridge模式。该模式分离对象的抽象和实现,这样两边都可以演化。
  6. Decorator模式。该模式用于动态给对象增加功能。

6中结构型设计模式的对比理解(Composite组合模式,Proxy代理模式,Flyweight享元模式,Facade门面模式,Bridge桥接模式,Decorator装饰器模式)相关推荐

  1. 面向对象程序设计(OOP设计模式)-结构型模式之装饰器模式的应用与实现

    课程名称:程序设计方法学 实验4:OOP设计模式-结构型模式的应用与实现 时间:2015年11月18日星期三,第3.4节 地点:理1#208 一.实验目的 加深对结构型设计模式的理解以及在开发中的实际 ...

  2. java设计模式之结构型设计模式

    结构型设计模式: 适配器(Adapter): 用途:将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的类可以一起工作. 场景: 你想使用一个已经存在的 ...

  3. java中装饰器_Java设计模式12:装饰器模式

    装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...

  4. 【python设计模式】6、装饰器模式

    哲学思想 装饰器模式是一种结构型设计模式,其哲学思想是通过组合和装饰对象来扩展其功能,而不需要修改其底层代码或继承新的类.它遵循了"开放封闭原则",即对扩展开放,对修改关闭. 该模 ...

  5. 设计模式--装饰器模式

    装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装.简单来说,装饰器模式就是 ...

  6. Java设计模式12:装饰器模式

    装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...

  7. 聊聊在Vue项目中使用Decorator装饰器

    戳蓝字" Web前端严选 " 关注我们哦 ! 前言 初衷: 前几天我在公司其它Vue项目中,发现了是用Decorator装饰器模式开发的,看起来整体代码还不错,于是就做了一下笔记分 ...

  8. 每天两个设计模式(三)装饰器模式(今天就一个)

    文章目录 装饰器模式 引言 概念分析 分析 适配器模式 解决套娃式功能 分析步骤 代码 再次升级 装饰器模式 引言 初看装饰器模式的时候,一脸懵逼,网上一堆博客,也是千篇一律,上来就是举例子,然后直接 ...

  9. JAVA开发的23种设计模式之 —  装饰器模式 代理器模式

    装饰器模式 概述 : 动态的给一个对象添加一些额外的职责,就增加功能来说,装饰器模式相比生成子类更加灵活 维基百科解释 : 通过使用修饰模式,可以在运行时扩充一个类的功能.原理是 :增加一个修饰类包裹 ...

最新文章

  1. 【Silverlight】Bing Maps开发应用与技巧三:Bing Maps Silverlight Control的离线开发
  2. 在OpenCV下写的直方图匹配(直方图规定化)C++源码!
  3. Get Form type using javascript in CRM 2011
  4. Java环境变量的配置 (Win10环境下)
  5. Mysql基本用法-left join、right join、 inner join、子查询和join-02
  6. TensorFlow:tensorflow之CIFAR10与ResNet18实战
  7. MFC使用简单总结(便于以后查阅)
  8. iOS 面试题分析(二)
  9. Matlab电路仿真
  10. xp系统打开计算机硬盘分区,如何在xp系统对硬盘进行分区
  11. 同一方法被多个Aspect拦截, 修改切面@Around @Before的执行顺序
  12. Linux系统命令行常识问答2
  13. cmake出错:Building inplace are not allowed. You should create a separate directory for Building.
  14. java 数据库密码加密解密方法
  15. wilcoxon rank sum test R代码
  16. js日期格式化yyyy-MM-dd
  17. 网易云信助力兴趣社交头部玩家,【微光】打造在线交友电影院
  18. jQuery实现购物车计算价格统计功能
  19. p,np,npc,np难问题,确定图灵机与非确定图灵机
  20. k8s-(七)暴露服务的三种方式

热门文章

  1. 以VGG为例,分析深度网络的计算量和参数量
  2. 简单的jsp权限管理
  3. CorelDRAW X7中相机滤镜呈现出的复古照片效果
  4. CalBioreagents艾美捷兔单克隆抗人Id1克隆5-3说明书
  5. mysql如何使用命令行操作_MySQL命令行基本操作
  6. Python足球战术板源代码,过一把足球教练的瘾,足球战术分析工具
  7. CorelDRAW制作半调网屏艺术效果
  8. 网站被百度降权了怎么办?
  9. antd-vue上传文件,并读取文件内容
  10. 关于协方差矩阵的概念及意义