阅读 2097

🐻iOS设计模式

设计模式,一个一个学,等到理解后,揉碎,分散,然后修改现有项目,思考哪些可以用到哪个设计模式。

设计模式之路

  • 熟悉阶段,好像每一种设计模式都符合当前的情况,不同的设计模式有歧义,有相似,有违背设计原则,似乎都能解决。别怕,挑一个自己觉得最合适的。
  • 使用阶段,会把各种设计模式混合使用,整的明明白白,但设计的会有些僵硬,缺少灵活性
  • 融汇贯通,设计模式烂与心中,写代码时,自然而然久用到了自己模式,根据设计模式的七大原则,写出优秀的代码
  • 出神入化,设计原则已经出现在你的潜意识里,并且已经开始尝试新的原则设计。

就像张无忌跟张三丰学太极时,全部学会,才是入门;全部忘掉,才算是渐入佳境,距离成神还早着呢。

设计模式原则一览表

  • 开闭原则是总纲,它告诉我们要对扩展开放,对修改关闭;
  • 里氏替换原则告诉我们不要破坏继承体系;
  • 依赖倒置原则告诉我们要面向接口编程;
  • 单一职责原则告诉我们实现类要职责单一;
  • 接口隔离原则告诉我们在设计接口的时候要精简单一;
  • 迪米特法则告诉我们要降低耦合度;
  • 合成复用原则告诉我们要优先使用组合或者聚合关系复用,少用继承关系复用。

一览表

名称 分类 思想 角色 示例
简单工厂模式 创建型 用个工厂来创建一个要求的相同种类东西 具体工厂类、抽象对象类、具体对象类 Factory生产 圆、方形、椭圆、菱形 的按钮
工厂方法模式 创建型 用个工厂来创建多个要求的相同种类东西 具体工厂类、抽象对象类、具体对象类 Factory生产 圆、方形、椭圆、菱形 的按钮,同时区分暗黑主题、还是正常模式
抽象工厂模式 创建型 用个工厂来创建多个要求的不相同种类东西 抽象工厂、工厂、抽象产品多种、具体产品多种 Factory生产 圆、方形、椭圆、菱形 的控件,同时区分暗黑主题、还是正常模式;控件包含按钮,UILabel、UIView、UIImageView
建造者模式 创建型 创建一个复杂的东西 指挥者、抽象建造者、具体建造者、被建造的对象 通过KFC点餐来学习建造者模式
单例模式 创建型 单一、重复使用、频繁使用 x XXManager,XXServer,UserDefault
= = = = =
适配器模式 结构型 把需适配者Adaptee,通过适配器Adapter,适配成可以供目标TargetA、B、C、D使用 ,注意ABCD用的都是Adaptee中的同样的功能,不是组合 Adaptee、Adapter、Target 通过撸一个滚动图来学习适配器模式
桥接模式 结构型 A想用B但是没办法通过继承组合等形式达成时 桥接文件,这里边应该是极其复杂的黑盒子 apple 提供了使用桥接的思想,一个是原生OC、Swift调用JS、另一个是Swift调用OC;我能想到的一个示例:我们用Swift自己去解析Lottie的json文件,然后修改里边的值,让其做动画、改变宽高、颜色
装饰器模式 结构型 动态的给对象增加方法 x swift中面向协议编程以及extension都是这种思想
外观模式 结构型 减少不同类之间的交互,提供统一接口 使用者、 外观、子功能 在获取资源类中,需要分别调用本地缓存和网络数据,最后把这个组合结果返回;实现隔离减少不同类之间的交互
代理模式 结构型 先占坑,异步操作 x 耗时操作,图片异步加载
享元模式 结构型 缓存系统,缓存在内存中、大量重复使用适合颗粒度较小的东西 x x
= = = = =
命令模式 (×) 行为型 把命令抽象成对象,具体的命令对象,给外界提供接口,同时负责命令的执行 抽象命令类、具体命令类、调用者、接收者 设计模式系列 6-- 命令模式
中介者模式 行为型 用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互 Mediator: 抽象中介者、ConcreteMediator: 具体中介者、Colleague: 抽象同事类、ConcreteColleague: 具体同事类 设计模式系列3--中介者模式
观察者模式 行为型 主动观察到状态改变,从而发生变化,一对多的场景 抽象目标 、目标、抽象观察者、观察者 KVO、Notification
状态模式 行为型 对象的行为取决于状态,环境类实际上就是拥有状态的对象,环境类有时候可以充当状态管理器(State Manager)的角色,可以在环境类中对状态进行切换操作 环境类、抽象状态类、具体状态类 设计模式系列9--状态模式
策略模式 行为型 定义一系列算法,把它们一个个的封装起来,并且使他们可以相互替换。策略模式使得算法可独立于使用它的客户端而变化 环境类、抽象策略类、具体策略类 X模块中有个分段函数,A、B、C需要X模块支持,但是对X模块中的分段函数有不同要求,这时,你可以在X模块中写if、else语句、或者switch语句,但这样违反开闭原则,所以,更好的方式是把函数算法封装起来,作为参数传进去。

创建型模式

  • 创建型模式在创建什么(What),由谁创建(Who),何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性。

  • 创建型模式隐藏了类的实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的。

  • 说明:创建对象时,使用到的模式

  • 关键字:build、构建、构造、创建、工厂模式

一、简单工厂模式

二、工厂设计模式

  • 场景:生产单一类型产品(大量,分给不同工厂制造)
  • 角色:抽象工厂、工厂、抽象产品、具体产品
  • 参见工厂模式三兄弟

三、抽象工厂模式

  • 场景:生产多种类型产品(大量,分给不同工厂制造)
  • 角色:抽象工厂、工厂、抽象产品多种、具体产品多种
  • 参见工厂模式三兄弟

四、建设者模式

五、单例模式

  • 场景:单一、重复使用、频繁使用
  • 注意:有些资源不再需要时,或者收到内存警告时,主动释放
  • 示例:XXManager,XXServer,UserDefault

结构型模式

  • 说明:某一个功能比较复杂时,如何可复用\组合形成复杂的、功能更为强大的结构
  • 关键字:框架、解耦、隔离、组合、结构
  • 结构型模式可以分为类结构型模式和对象结构型模式
    • 类结构型模式关心类的组合,由多个类可以组合成一个更大的
    • 对象结构型模式关心类与对象的组合,通过关联关系使得在一 个类中定义另一个类的实例对象,然后通过该对象调用其方法。 根据“合成复用原则”,在系统中尽量使用关联关系来替代继 承关系,因此大部分结构型模式都是对象结构型模式。

一、适配器模式

二、桥接模式

  • A想用B但是没办法通过继承组合等形式达成时
  • 桥接文件,这里边应该是极其复杂的黑盒子
  • apple 提供了使用桥接的思想,一个是原生OC、Swift调用JS、另一个是Swift调用OC;
  • 我能想到的一个示例:我们用Swift自己去解析Lottie的json文件,然后修改里边的值,让其做动画、改变宽高、颜色

三、装饰器模式

  • 说明:动态的扩展方法、功能
  • 示例:swift中面向协议编程以及extension都是这种思想

四、外观模式

  • 说明:减少不同类之间的交互,提供统一接口

  • 示例:比如获取资源类中,需要调用本地缓存、网络数据,实现隔离减少不同类之间的交互

  • 代码: https://www.raywenderlich.com/477-design-patterns-on-ios-using-swift-part-1-2#toc-anchor-007

五、代理模式

  • 说明:先占坑,后操作
  • 示例:耗时操作,图片异步加载

六、享元模式

  • 说明:缓存系统,缓存在内存中、大量重复使用适合颗粒度较小的东西
  • 示例:未知

行为型模式

  • 说明:通过相互通信与协作完成某些复杂功能,一个对象在运行时也将影响到其他对象的运行

  • 关键字:观察、通知、MVC、反馈、监控

  • 行为型模式分为类行为型模式和对象行为型模式两种:

    • 类行为型模式:类的行为型模式使用继承关系在几个类之间分配行为,类行为型模式主要通过多态等方式来分配父类与子类的职责。
    • 对象行为型模式:对象的行为型模式则使用对象的聚合关联关系来分配行为,对象行为型模式主要是通过对象关联等方式来分配两个或多个类的职责。根据“合成复用原则”,系统中要尽量使用关联关系来取代继承关系,因此大部分行为型设计模式都属于对象行为型设计模式。

一、命令模式

二、中介者模式

  • 说明:A、B之间不交流,通过C来完成沟通,
  • 示例:比如MVC中的 Model、View不直接交流,而是通过Controller交流;现实生活中的中介公司,干的就是这个活,Controller处理的事情太多,会变的越来越复杂,臃肿,这种模式的弊端也是如此。
  • 设计模式系列3--中介者模式

三、观察者模式

  • 说明:主动观察到状态改变,从而发生变化
  • 示例:KVO、Notification

四、状态模式

  • 说明:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
  • 示例:设计模式系列9--状态模式
  • 个人理解:假如在不同状态下,可能有同样的操作,这时把状态封装成类,把操作定义成协议,每个状态类遵守这个协议,并实现。

五、策略模式

  • 说明:定义一系列算法,把它们一个个的封装起来,并且使他们可以相互替换。策略模式使得算法可独立于使用它的客户端而变化。
  • 示例1:设计模式系列8--策略模式
  • 示例2:X模块中有个分段函数,A、B、C需要X模块支持,但是对X模块中的分段函数有不同要求,这时,你可以在X模块中写if、else语句、或者switch语句,但这样违反开闭原则,所以,更好的方式是把函数算法封装起来,作为参数传进去。

参考链接:

  • https://juejin.im/post/6844903934230806535
  • https://design-patterns.readthedocs.io/zh_CN/latest/index.html
  • https://juejin.im/user/3526889030556574/posts

本文使用 mdnice 排版