iOS设计模式 - 结构型

结构型设计模式

用于处理类或对象的组合

一、桥接模式 - Bridge Pattern

把事物对象和其具体特征分享开来,使它们可以各自独立变化。
圆形三角形归于抽象的形状之下,而画圆画三角归于实现行为的画图之下,然后由形状调用画图
桥接模式是为了实现两个接口结合的多样化而设计的一个模式。目的是为了结合的更好。

桥接模式用于设计的前期,即在设计类时将类规划为逻辑和实现两个大类,是他们可以分别精心深化。

适配器模式用于设计完成之后,当发现设计完成的类无法协同工作时,可以采用适配器模式。
然而很多情况下,在设计初期就要考虑适配器模式的使用,比如在涉及到大量第三方应用接口的情况。

桥接模式UML
  • Abstraction (abstract class)抽象类
    定义抽象接口,维护 Implementor 的引用
  • Refined Abstraction (normal class) 抽象类的普通类
    抽象类 Abstraction 的子类,扩展抽象定义的接口
  • Implementor (interface) 实现类抽象
    定义实现类的接口
  • ConcreteImplementor (normal class) 实现类的普通类
    实现 Implementor 的接口

二、适配器模式 - AdapterPattern

适配器模式(AdapterPattern)也被称为包装样式或包装。将一个类的接口转换成用户所期待的。一个适配器使得因接口不兼容而不能在一起工作的类能在一起工作。做法是将自己的接口包裹在一个已知类中。

  • 对象适配器模式
    适配器容纳一个包裹的类的实例,适配器调用被包裹对象的物理实体。


    对象适配器模式UML
  • 类适配器模式
    这种适配器下,适配器继承自己实现的类。


    类适配器模式UML

参考:维基百科https://zh.wikipedia.org/wiki/适配器模式

- 例子,方便理解

  • 桥接模式
    日常电器用电,用电源线(实现类的抽象)电器(抽象类)电源插座桥接
  • 适配器模式
    但有部分电器(如手机、电脑)并不能直接使用120V进行充电,所以中间需要再加一个充电器(电源适配器)

代码示例(Adapter 也在 Bridge 中)
https://github.com/FMR-Murphy/iOS-Design-Patterns/tree/main/桥接模式%20-%20BridgePattern

三、组合模式 - Compsite Pattern

组合模式使得用户对单个对象和组合对象的使用具有一致性。
将对象组合成树形结构以表示部分、整体的层次结构,又叫部分整体模式,可以用来描述整体和部分的状态。。是用于把一组相似的对象当作单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构模式。它创建了对象组的树形结构。

  • 一致性组合设计:(也叫透明式组合)所有对象都是使用同一个接口,不会区分对象之间的差别,使用者使用起来是区分不了的,树叶构件也会实现树枝构件的方法。但是是空实现,需要抛出异常。
  • 安全性组合设计:树叶构件和树枝构件的接口需要区分开来,在实际使用时需要使用者区分构件类型,对于使用者来说就推动了透明性,但也不会在调用方法时抛出异常。
组合模式UML
  • Component 抽象构件
    这是一个抽象角色,给参加组合的对象定义出公共的接口及其默认行为,用来约束所有的子对象。组合对象通常把它所包含的子对象当作类型为Component的对象。在安全式的组合模式里,构建角色并不定义出管理子对象的方法,这一定义由树枝对象给出。
  • Leaf 叶构件
    树叶对象没有下级子对象。定义出参加组合的原始对象行为。
  • Composite 树枝构件
    代表参加组合的有下级子对象的对象。树枝构件类给出所有的管理子对象的方法,如add()remove()以及getChild()等。

- 例子,方便理解
文件系统就是典型的组合模式系统。
示例代码
https://github.com/FMR-Murphy/iOS-Design-Patterns/tree/main/组合模式%20-%20CompositePattern

四、外观模式 - Facade Pattern

为复杂的子系统调用提供一个统一的入口供客户端调用。使子系统更容易使用。


外观模式UML
  • Facade 外观类
    为子系统中Packages1、2、3提供一个共同的对外接口。
  • Clients 客户对象
    通过一个外观接口访问子系统中各接口的资源。
  • Packages 内部子系统
    客户可以通过外观接口访问的内部子系统。

五、装饰模式 - Decorator Pattern

又叫装饰者模式。装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。
它通过创建一个包装的对象,也就是装饰来包裹真实的对象。但在不需要用到新功能的地方,它可以直接调用原来的类中的方法。装饰类必须有和原来类相同的接口。

装饰模式UML

- 例子,方便理解

  • 外观模式
    客厅的灯有四种状态:外圈亮、内圈亮、全亮、全灭,本来需要一个外圈开关,一个内圈开关。但现在通过内部程序收到开关信号后循环展示四种状态,就只需要一个开关。可以说这个开关就是给我们的一个外观类
  • 装饰模式
    还是这个开关,过年为了喜庆,或者平时为了美观,在不使用修改内部类(拆解、激光印花等物理修改),不使用继承(更换另一个开关的“子类“)的情况下,给开关加个贴纸,动态的扩展开关的功能喜庆
    开关贴

六、享元模式 - Flyweight Pattern

使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能的相似物件。它适合用于只是因重复而导致使用无法令人接受的大量内在的大物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。
享元模式运用共享技术有效的支持大量细粒度的对象。
内蕴状态存储的内部,不随环境的改变而有所不同,是可以共享。
外蕴状态是不可以共享的,它随环境的改变而改变。因此外蕴状态是由客户端来保持(因为环境的变化是由客户端引起的)。

角色结构

  • Client 客户端角色
    维护对所有享元对象的引用,而还需要存储对应的外蕴状态。
  • Flyweight Factory 享元工厂角色
    负责创建和管理享元角色。要想达到共享的目的,这个角色很关键。
  • Flyweight 抽象享元角色
    为具体享元角色规定了必须实现的方法,而外蕴状态就是以参数的形式通过此方法传入。
  • Flyweight1具体享元角色
    实现抽象角色规定的方法,并存储内部状态
享元模式

- 例子,方便理解
-UILabel等显示本文的时候字体、字号、颜色等文字属性只保存一份。NSAttributedString按索引范围Range保存文字属性。而不是每个字都单独保存一份属性。
-常用的UITableViewCellUICollectionViewCell也是享元模式。需要时从缓存池匹配现有的同类对象,如果找到就直接使用。未找到再创建新对象。

七、代理模式 - Proxy Pattern

对其他对象提供一种代理,以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理的使用可以简单地转发到真实对象,或者可以提供额外的逻辑。在代理中,可以提供额外的功能,例如,当对真实对象的操作是资源密集型时进行缓存,或者在调用对真实对象进行操作之前检查先决条件。对于客户端,使用代理对象与使用真实对象类似,因为两者都实现了相同的接口。

当一个复杂对象的多份副本须存在时,代理模式可以结合享元模式以减少存储器用量。典型作法是创建一个复杂对象,及多个代理者。每个代理者会引用到原来的复杂对象。

在 iOS 中可以使用NSProxy实现多继承

代理模式

  • Subject 抽象角色
    通过接口或抽象类声明真实角色实现的业务方法。
  • Proxy代理角色
    实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
  • RealSubject 真实角色
    实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

需要与delegate进行区分

  • Proxy
    中介(代理)持有若干对象(房产),这些对象(房产)实现了一个共同接口(对外出租),客户要租房,直接找中介,中介帮我选择符合我要求的对象(房产)(在对真实进行操作之前检查先决条件),比每个客户都持有若干对象,挨个查看是否符合自己要求方便快捷的多。
    Proxy注重过程
  • delegate
    任务调用和分配,注重结果,属于行为型模式,不在GoF23种设计模式之中。
    客户端在合适时机把任务交给委托者(有可能是多个),委托者做不做,怎么做,都不关心。
    客户委托朋友(delegate)帮忙找房,但怎么找,在哪找,找没找,具体细节都是隐藏的。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349