<1>适配器模式
-
何为适配器模式?
适配器模式将一个类的接口适配成用户所期待的。一个适配器通常允许因为接口不兼容而不能一起工作的类能够在一起工作,做法是将类自己的接口包裹在一个已存在的类中。(联想一下现实生活中的各类适配,就比较容易理解了) -
如何使用适配器模式?
以下情况比较适合使用 Adapter 模式:
- 当你想使用一个已经存在的类,而它的接口不符合你的需求;
- 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作;
- 你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口,对象适配器可以适配它的父亲接口。
-
适配器模式的优缺点?
优点:降低数据层和视图层(对象)的耦合度,使之使用更加广泛,适应复杂多变的变化。
缺点:降低了可读性,代码量增加,对于不理解这种模式的人来说比较难看懂。
<2>策略模式
-
何为策略模式?
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。 -
如何使用策略模式?
在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。- 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
- 一个系统需要动态地在几种算法中选择一种。
- 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
- 注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
-
策略模式的优缺点?
优点:简化操作,提高代码维护性。算法可以自由切换,避免使用多重条件判断,扩展性良好。
缺点:在使用之前就要确定使用某种策略,而不是动态的选择策略。策略类会增多,所有策略类都需要对外暴露。
<3>观察者模式
- 何为观察者模式?
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 - 如何使用观察者模式?
一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。 - 观察者模式的优缺点?
优点:
- 观察者和被观察者是抽象耦合的。
- 建立一套触发机制。
缺点:
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
-
gitHub示例代码
iOS设计模式之观察者模式 -
设计模型图(在敲代码的时候要多想想这个模型图)
<4>原型/外观模式
- 何为原型/外观模式?
原型模式:(Prototype Pattern)用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。
外观模式:(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。 - 如何使用原型/外观模式?
原型模式:
- 当一个系统应该独立于它的产品创建,构成和表示时。
- 当要实例化的类是在运行时刻指定时,例如,通过动态装载。
- 为了避免创建一个与产品类层次平行的工厂类层次时。
- 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
外观模式:
- 客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。
- 定义系统的入口。
- 原型/外观模式的优缺点?
原型模式:
优点:性能提高,逃避构造函数的约束。
缺点:
- 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易。
- 必须实现 Cloneable 接口。
- 逃避构造函数的约束。
外观模式
优点:减少系统相互依赖、提高灵活性、提高了安全性。
缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
- 在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。(以后会在工厂模式代码中体现)
github原型模式示例源码
github外观模式示例代码
外观模式模型图如下
<5>装饰模式
- 何为装饰模式?
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。 - 如何使用装饰模式?
在不想增加很多子类的情况下扩展类。 - 装饰模式的优缺点?
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。 - github示例代码iOS设计模式之装饰模式
模型图如下
<6>工厂模式
- 何为工厂模式?
- 这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
- 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
- 如何使用工厂模式?
- 我们明确地计划不同条件下创建不同实例时。
- 作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
- 工厂模式的优缺点?
优点:
- 一个调用者想创建一个对象,只要知道其名称就可以了。
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
- 屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
- 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
- 抽象工厂模式
- 抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
- 在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
<7>桥接模式
- 何为桥接模式?
- 桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
- 这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。
- 如何使用桥接模式?
- 在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
- 实现系统可能有多个角度分类,每一种角度都可能变化。
- 把这种多角度分类分离出来,让它们独立变化,减少它们之间耦合。
- 桥接模式的优缺点?
优点 :抽象和实现的分离、优秀的扩展能力、实现细节对客户透明。
缺点:桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。 - githubiOS设计模式之桥接模式
模型图如下
<8>代理模式
- 何为代理模式?
- 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
- 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
- 如何使用代理模式?
- 在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
- 想在访问一个类时做一些控制。
- 代理模式的优缺点?
优点:
- 职责清晰、高扩展性、智能化。
缺点:
- 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
- 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
<9>单例模式
- 何为单例模式?
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
- 如何使用单例模式?
当您想控制实例数目,节省系统资源的时候。 - 单例模式的优缺点?
优点:- 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
- 避免对资源的多重占用比如写文件操作。
缺点:
- 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
- githubiOS设计模式之单例模式
(注:代码中的单例是“严格”的单例) - github单例模式优化本地存储
<10>备忘录模式
- 何为备忘录模式?
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。
- 如何使用备忘录模式?
很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃。 - 备忘录模式的优缺点?
优点:
- 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
- 实现了信息的封装,使得用户不需要关心状态的保存细节。
缺点:
- 消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
<11>生成器模式
- 何为送生成器模式?
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 - 如何使用生成器模式?
- 主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
- 一些基本部件不会变,而其组合经常变化的时候。
- 生成器模式的优缺点?
优点:
- 建造者独立,易扩展。
- 便于控制细节风险。
缺点:
- 产品必须有共同点,范围有限制。
- 如内部变化复杂,会有很多的建造类。
- 使用场景
- 需要生成的对象具有复杂的内部结构。
- 需要生成的对象内部属性本身相互依赖。
注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
- githubiOS设计模式之制造者模式(参考制造汽车的过程)
-
制造者模式思维导图
<12>命令模式
- 何为命令模式?
命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。 - 主要解决的问题?
在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。 - 如何使用命令模式?
在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。 - 关键代码?
定义三个角色:
- received 真正的命令执行对象
- Command
- invoker 使用命令对象的入口
- 命令模式的优缺点?
优点:降低了系统耦合度,新的命令可以很容易添加到系统中去。
缺点:使用命令模式可能会导致某些系统有过多的具体命令类。 - 使用场景
认为是命令的地方都可以使用命令模式 - githubiOS设计模式之命令模式(实现View的明亮变化)
<13>组合模式
- 何为组合模式?
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。 - 主要解决的问题?
它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。 - 如何使用适配器模式?
树枝和叶子实现统一接口,树枝内部组合该接口。 - 关键代码?
树枝内部组合该接口,并且含有内部属性 List,里面放 Component。 - 适配器模式的优缺点?
优点: 高层模块调用简单、节点自由增加。
缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。 - 使用场景?
部分、整体场景,如树形菜单,文件、文件夹的管理。
(注:定义时为具体类。) - githubiOS设计模式之组合模式(模拟文件夹)