GOF设计模笔记式之结构模型

1 前言

上一篇我们研究了创建型模式,这一篇们开始研究结构模型,这里主要解决合成还是继承的问题。如何通过适当的方法给类解耦。这里是我们主要考虑的问题,这里6种设计模式的关系我就先不研究,了解每一种模式再说。

2 模式特点

这里主要介绍六中设计模式的特点与结构,记录下自己的想法。

2.1 ADAPTER(适配器) — 类对象结构型模式

2.1.1. 意图

将一个类的接口转换成客户希望的另外一个接口。 A d a p t e r模式使得原本由于接口不兼容

而不能一起工作的那些类可以一起工作。

2.1.2 适用性

以下情况使用Adapter模式

  • 你想使用一个已经存在的类,而它的接口不符合你的需求。
  • 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
  • (仅适用于对象Adapter)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。

2.1.3 结构图

2.1.4 效果

类适配器和对象适配器有不同的权衡。类适配器

  • 用一个具体的Adapter类对Adapter和Target进行匹配。结果是当我们想要匹配一个类以及所有它的子类时,类Adapter不能胜任工作。
  • 使得Adapter可以重定义Adaptee的部分行为,因为Adapter是Adaptee的一个子类。
  • 仅仅引入了一个对象,并不需要额外的指针以间接得到 Adaptee。对象适配器则
  • 允许一个Adapter与多个Adaptee — 即Adaptee本身以及它的所有子类 (如果有子类的话)—同时工作。Adapter也可以一次给所有的Adaptee添加功能。
  • 使得重定义Adaptee的行为比较困难。这就需要生成 Adapte e的子类并且使得Adapter引用

    这个子类而不是引用Adaptee本身。

2.1.5 注意

这里面比价复杂,适配器模式主要是转换数据格式的。也就是接口,listview中的adapter就是adapter模式

2.2 BRIDGE(桥接) — 对象结构型模式

2.2.1 意图

将抽象部分与它的实现部分分离,使它们都可以独立地变化。

2.2.2 适用性

以下一些情况使用Bridge模式:

  • 你不希望在抽象和它的实现部分之间有一个固定的绑定关系。 例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
  • 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时 Bridge模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
  • 对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
  • (C++)你想对客户完全隐藏抽象的实现部分。在 C++中,类的表示在类接口中是可见的。
  • 有许多类要生成。这样一种类层次结构说明你必须将一个对象分解成两个部分。 R u m b a u g h称这种类层次结构为“嵌套的普化”(nested generalizations) 。
  • 你想在多个对象间共享实现(可能使用引用计数) ,但同时要求客户并不知道这一点。

2.2.3 结构图

2.2.4 效果

Bridge模式有以下一些优点:

  1. 分离接口及其实现部分 一个实现未必不变地绑定在一个接口上。抽象类的实现可以在运行时刻进行配置,一个对象甚至可以在运行时刻改变它的实现。将Abstraction与Implementor分离有助于降低对实现部分编译时刻的依赖性,当改变一个实现类时,并不需要重新编译Abstraction类和它的客户程序。为了保证一个类库的不同版本之间的二进制兼容性,一定要有这个性质。另外,接口与实现分离有助于分层,从而产生更好的结构化系统,系统的高层部分仅需知道Abstraction和Implementor即可。
  2. 提高可扩充性 你可以独立地对Abstraction和Implementor层次结构进行扩充。

2.2.5 注意

有助于解耦

2.3 COMPOSITE(组合) — 对象结构型模式

2.3.1 1. 意图

将对象组合成树形结构以表示“部分 -整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。

2.3.2 适用性

  • 你想表示对象的部分-整体层次结构。
  • 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

2.3.3结构图

2.3.4效果

  • 定义了包含基本对象和组合对象的类层次结构 基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断的递归下去。客户代码中,任何用到基本对象的地方都可以使用组合对象。
  • 简化客户代码 客户可以一致地使用组合结构和单个对象。通常用户不知道 (也不关心)处理的是一个叶节点还是一个组合组件。这就简化了客户代码 , 因为在定义组合的那些类中不需要写一些充斥着选择语句的函数。
  • 使得更容易增加新类型的组件 新定义的Composite或Leaf子类自动地与已有的结构和客户代码一起工作,客户程序不需因新的Composite类而改变。
  • 使你的设计变得更加一般化 容易增加新组件也会产生一些问题,那就是很难限制组合中的组件。有时你希望一个组合只能有某些特定的组件。使用Composite时,你不能依赖类型系统施加这些约束,而必须在运行时刻进行检查。

2.3.5 注意

这里最好的例子是view类其实就是一个递归调用。来解析特定的内容。有利于解耦。并且对于自己不知道内容的编程非常重要

2.4 DECORATOR(装饰) — 对象结构型模式

2.4.1 意图

动态地给一个对象添加一些额外的职责。就增加功能来说, dectortor模式相比生成子类更为灵活。

2.4.2 适用性

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 处理那些可以撤消的职责。
  • 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

2.4.3结构图

2.4.4 效果

Decorator模式至少有两个主要优点和两个缺点:

  1. 比静态继承更灵活 与对象的静态继承(多重继承)相比, Decorator模式提供了更加灵活的向对象添加职责的方式。可以用添加和分离的方法,用装饰在运行时刻增加和删除职责。相比之下,继承机制会产生许多新的类,并且会增加系统的复杂度。此外,为一个特定的Compoent类提供多个不同的Decorator类,这就使得你可以对一些职责进行混合和匹配。使用Decorator模式可以很容易地重复添加一个特性。
  2. 避免在层次结构高层的类有太多的特征Decorator模式提供了一种“即用即付”的方法来添加职责。它并不试图在一个复杂的可定制的类中支持所有可预见的特征,相反,你可以定义一个简单的类,并且用Decorator类给它逐渐地添加功能。可以从简单的部件组合出复杂的功能。这样,应用程序不必为不需要的特征付出代价。同时也更易于不依赖于Decorator所扩展(甚至是不可预知的扩展)的类而独立地定义新类型的Decorator。扩展一个复杂类的时候,很可能会暴露与添加的职责无关的细节。
  3. Decorator与它的Compoent不一样 Dectorator是一个透明的包装。如果我们从对象标识的观点出发,一个被装饰了的组件与这个组件是有差别的,因此,使用装饰时不应该依赖对象标识。
  4. 有许多小对象 采用Dectorator模式进行系统设计往往会产生许多看上去类似的小对象,这些对象仅仅在他们相互连接的方式上有所不同,而不是它们的类或是它们的属性值有所不同。尽管对于那些了解这些系统的人来说,很容易对它们进行定制,但是很难学习这些系统,排错也很困难。

2.4.5 注意

这种设计模式感觉平时不太常用。

2.5 FACADE(外观) — 对象结构型模式

2.5.1 意图

为子系统中的一组接口提供一个一致的界面, F a c a d e模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

2.5.2 适用性

在遇到以下情况使用Facade模式

  • 当你要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。Facade可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过Facade层。
  • 客户程序与抽象类的实现部分之间存在着很大的依赖性。引入Facade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
  • 当你需要构建一个层次结构的子系统时,使用Facadee模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过Facade进行通讯,从而简化了它们之间的依赖关系。

2.5.3 结构图

2.5.4 效果

Facade模式有下面一些优点:

  1. 它对客户屏蔽子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便。
  2. 它实现了子系统与客户之间的松耦合关系,而子系统内部的功能组件往往是紧耦合的。松耦合关系使得子系统的组件变化不会影响到它的客户。Facade模式有助于建立层次结构系统,也有助于对对象之间的依赖关系分层。Facade模式可以消除复杂的循环依赖关系。这一点在客户程序与子系统是分别实现的时候尤为重要。在大型软件系统中降低编译依赖性至关重要。在子系统类改变时,希望尽量减少重编译工作以节省时间。用Facade可以降低编译依赖性,限制重要系统中较小的变化所需的重编译工作Facade模式同样也有利于简化系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。
  3. 如果应用需要,它并不限制它们使用子系统类。因此你可以在系统易用性和通用性之间加以选择。

2.5.5 注意

一切目的是为了封装。功能封装,组件解耦。

2.6 FLYWEIGHT(享元) — 对象结构型模式

2.6.1 意图

运用共享技术有效地支持大量细粒度的对象。

2.6.2 适用性

Flyweight模式的有效性很大程度上取决于如何使用它以及在何处使用它。当以下情况都成立时使用Flyweight模式:

  • 一个应用程序使用了大量的对象。
  • 完全由于使用大量的对象,造成很大的存储开销。
  • 对象的大多数状态都可变为外部状态。
  • 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
  • 应用程序不依赖于对象标识。由于Flyweight对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。

2.6.3 结构图

2.6.4 效果

使用Flyweight模式时,传输、查找和 /或计算外部状态都会产生运行时的开销,尤其当Flyweight原先被存储为内部状态时。然而,空间上的节省抵消了这些开销。共享的Flyweight越多,空间节省也就越大。

存储节约由以下几个因素决定:

? 因为共享,实例总数减少的数目

? 对象内部状态的平均数目

? 外部状态是计算的还是存储的

2.6.4 注意

我不是很明白。在当前我考虑不到大量的类对象的创建。

2.7 PROXY(代理) — 对象结构型模式

2.7.1 意图

为其他对象提供一种代理以控制对这个对象的访问。

2.7.2 适用性

在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用Proxy模式。下面是一些可以使用Proxy模式常见情况:

  1. 远 程 代 理 ( Remote Proxy) 为 一 个 对 象在 不 同 的 地 址 空间 提 供 局 部 代 表。
  2. 虚代理(Virtual Proxy)根据需要创建开销很大的对象。
  3. 保护代理(Protection Proxy)控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。

2.7.3 结构图

2.7.4 效果

Proxy模式在访问对象时引入了一定程度的间接性。根据代理的类型,附加的间接性有多种用途:

  1. Remote Proxy可以隐藏一个对象存在于不同地址空间的事实。
  2. Virtual Proxy 可以进行最优化,例如根据要求创建对象。
  3. Protection Proxies和Smart Reference都允许在访问一个对象时有一些附加的内务处理(Housekeeping task) 。

2.7.5 注意

这是个很有用的模式,

分析

时间: 2024-08-03 22:50:23

GOF设计模笔记式之结构模型的相关文章

自适应设计与响应式设计

目前非常流行自适应设计与响应式设计,而且经常让人混淆,自适应设计不应与自适应布局混为一谈,它们是完全不一样的概念. 在这先说明下这两者的异同: 自从移动终端飞速发展以来,各种各样的机型突飞猛进,很多网站的解决方法,是为不同的设备提供不同的网页,比如专门提供一个mobile版本,或者iPhone/iPad版本.这样做固然保证了效果,但是比较麻烦,同时要维护好几个版本,而且如果一个网站有多个portal(入口),会大大增加架构设计的复杂度. 于是,很早就有人设想,能不能"一次设计,普遍适用"

paip.自适应网页设计 跟 响应式 设计的区别跟原理and实践总结

建立map的方式(其实用的是json实现方式) var a = {}; a["key1"] = "value1"; a["key2"] = "value2"; 既然是个map就有检索某个键是否存在的方法,这样写 if ("key1" in a) { // something } else { // something else } 简单的一句话声明map里面的key和value的方式: var a = {'

《AxureRP原型设计学习笔记》之骨头班门弄斧篇

懒骨头(http://blog.csdn.net/iamlazybone QQ:124774397 青岛) ---- 前言 ---- AxureRP中的RP:Rapid Prototyping,快速原型. 这是产品经理的神奇,作为开发来搞这个东西,有点班门弄斧. 最近边查边搞了一个丑陋的app原型,一点心得,简计于此. mac下的AxureRP装完之后,默认打开是不显示程序界面的.别跟骨头似的以为没装好,重新下载安装.新建或打开即可. 这是软件界面: ---- 控件 ---- 不建议初学者首先下

paip.自适应网页设计 跟 响应式 设计方法与工具补充(2)o54

#-----响应式 设计框架 Bootstrap比较热门. Foundation 号称是世界上最先进的响应式前端框架. #---绝对不要使用相对地高度...只使用相对地宽度..特别大的布局上... #----------字体的自适应vw 使用em好像不生效... 使用vw走ok....  font-size: 4vw;   适合320*480-----600*900等... 顺便,要有个vmin,最小字体了.贝儿.太小李看不见.. 手动大小窗口,都能自己适合了.. 作者 老哇的爪子 Attila

数模笔记:公平席位的分配问题

数模笔记:公平席位的分配问题 基础 案列 某展会,AB双方根据人数分配席位: 衡量公平的数量指标: p1/n1=p2/n2.此时对AB均公平. p1/n1>p2/n2.此时对A不公平,因为对A放来说,每个席位相对应的人数比率更大. 绝对不公平度 定义: p1/n1-p2/n2 = 对A的绝对不公平度 问题: /*情况1*/ p1=150, n1=10, p1 /n1=15 p2=100, n2=10, p2 /n2=10 /*情况2*/ p1=1050, n1=10, p1 /n1=105 p2

23种设计模式式之Singleton(单例设计模)【学习笔记】

单例模式是设计模式中最简单,他要求设计者保证该类只有一个实例,之前我是挂载脚本实现单例, 该方法非常简单,使用的直接调用Singleton.instance就可以了 using UnityEngine; using System.Collections; public class Singleton : MonoBehaviour { public static Singleton instance; void Awake(){ instance = this; } } 但是这种写法并不规范,因

响应式web设计读书笔记

1.媒体查询可以在链接link标签和具体的CSS中使用: 2.通过<link>标签的 media 属性为样式表指定设备类型和其他条件  中间用and和()来分隔,如下 <link rel="stylesheet" media="screen and (orientation: portrait) and (min-width: 800px)" href="800wide-portrait-screen.css" /> 3.

《重构—改善既有代码的设计》笔记

为什么要重构 改进软件设计,消除重复代码 保持代码易读.易修改 提高编程速度(良好设计师维持软件开发速度的根本) 发现BUG 什么时候重构 事不过三,三则重构(三次法则) 添加功能时一并重构 修改错误时一并重构 复审代码时一并重构 问题代码 重复的代码 过长函数 过大类 过长参数列表 发散式变化 霰弹式修改 依恋情节 数据泥团 基本型别偏执 switch惊悚现身 冗赘类 夸夸其谈未来性 令人迷惑的暂时值域 过度耦合的消息链 中间转手人 狎昵关系 异曲同工的类 不完美的程序库类 纯稚的数据类 被拒

Responsive设计 (响应式设计)

一.什么是响应式设计 维基百科是这样对响应式作的描述:“Responsive设计简单的称为RWD,是精心提供各种设备都能浏览网页的一种设计方法,RWD能让你的网页在不同的设备中展现不同的设计风格.” 响应式布局设计要考虑到元素布局的秩序,需要满足三个条件: 网站必须建立在灵活的流体网格基础上 流体网格,这种网格设计将每个格子使用百分比单位来控制网格大小,这样做让网格大小随时根据屏幕尺寸大小做出相对应的比例缩放 引用到网站的图片必须是可伸缩的 弹性图片指的是 不给图片设置固定尺寸,而是根据流体网格