设计模式
没有最好的设计模式, 只有最适合的设计模式
1.建造者模式
建造者模式顾名思义,类似一个大楼都是按照一砖一瓦建造完成, 他通常结合链式调用一起使用该模式Android 比较热门的第三方框架均有使用
举例:Rxjava, Retrofit, Okhttp, Geendao, 等等
2.观察者模式
观察者模式是一种行为模式,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。(观察者类似中国的看客(解耦))
第三方运用框架:
Rxjava, EventBus
3.工厂模式
创建一个接口, 有调用者去决策实例那个类
4.抽象工厂模式
抽象工厂更像对工厂模式的一种升华, 正常工厂模式产生的是单一的固定, 抽象工厂产生的对象不是但一固定的
举例:
工厂模式的毛巾厂只能生产毛巾
抽象工厂模式的毛巾厂, 除了可以生产毛巾, 还可以生产袜子, 衣服
优缺点:
1.工厂模式职能相对但一, 但是比较好管理
2.抽象工厂职能多样向, 不好管理
5. 策略模式模式
策略设计模式是将一系列的算法通过封装, 使得算法之间可以相互替换。策略设计模式的目的是让算法独立于使用的客户而变化
Screenshot from 2021-05-16 13-21-41.png
6. 状态模式
状态设计模式和策略设计模式结构类型类似, 但是行为目的在本质完全不一样.
策略设计模式: 行为是彼此独立,可相互调换
状态设计模式: 由于要维护状态,行为是平行的, 不可替换的.
image.png
举例:
android wifi 的状态管理
7. 责任链模式模式
责任链是一种行为型设计模式, 一个行为从链条首端开始依次向下传递, 知道有对象处理这个消息.(下游可以有无数个子节点)
举例:
安卓事件分发机制是责任链最经典的应用
8. 解析器模式模式
解析器模式在设计模式用的比较少它是一种对文法解释作用的模式,比较经典的案例就是AndroidManifest.mk,AndroidManifest.mk 文件定义了service, activity等等, 在解析是PackageParse 会将这些标签进行分离实现, 解析执行到各个组件的对象中, 进而更方便的执行
解析器模式最核心的是分离实现, 解析执行执行
分离实现: 将对应文案分离成对应的实现对象
解析执行: 从对象中拿到对应的属性信息, 进行对象的创建和执行
举例:
androidmonifest.mk 通过PackageParse 解析封装的过程
9. 命令模式模式
image.png命令模式是将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
优点: 降低系统耦合 , 十分便捷的支持新的命令插入
缺点: 产生了过多的命令类
举例:
Android键盘事件 notifyArgs 传递给inputDispatcher 的过程.
10. 原型模式
原型设计模式是指按照一个对象的原型,拷贝出一份或者多份的复制对象, 一般原型需要实现clonable 进行对象的copy
优点: 解决来回创建对象导致的资源损耗
浅度克隆: 原型实现了cloneable 但是原型内部属性存在对象引用, 原型对象子属性对象变化会导致克隆的对象的内部引用的原型的属性变化.
深度克隆: 原型及其内部的子类也实现了cloneable, 原型内部子属性对象(变量)变化不会导致克隆的对象的内部引用的原型的属性变化.
缺点: 需要为每个原型以及原型内部子类实现cloneable进行深度克隆, 过程繁琐
举例:
ArrayList clone 的过程, 因此需要注意arrayList clone 是浅克隆, 子条目对象内容被修改, 其他的clone 出来的克隆体的子条目内容也会随之变化.
11. 备忘录模式
备忘录模式是一种行为模式, 该设计模式用于保存当前状态, 用于再次恢复之前的状态
举例:
activity 的 界面退出前onSaveInstanceState 保存当前状态, onRestoreInstanceState 恢复之前的状态.
12. 迭代器模式
迭代器模式是一种行为模式, 迭代器模式产生的目的是在客户端和容器之间插入一个迭代器, 解决容器自己提供遍历方法的导致过多内部细节暴露问题
优点:
(1)访问一个聚合对象的内容而无须暴露它的内部表示。
(2)遍历任务交由迭代器完成,这简化了聚合类。
(3)它支持以不同方式遍历一个聚合,甚至可以自定义迭代器的子类以支持新的遍历。
(4)增加新的聚合类和迭代器类都很方便,无须修改原有代码。
(4)封装性良好,为遍历不同的聚合结构提供一个统一的接口。
缺点:增加了类的个数,这在一定程度上增加了系统的复杂性。
举例:
arraylist, map, sqllite的游标查询
13. 模板方法模式
模板设计模式是一种行为模式的设计模式,它定义了最外层的框架, 并将一些步骤扩展到子类, 使得子类不改变框架结构就能重新定义某些特殊结构
举例:
android 中的四大组件是模板模式的经典使用案例, 暴露出一些接口用于子类构建和设置对应参数
14. 访问者模式
访问者(Visitor)模式的定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。
(简单来说就是创建不同的访问者对象, 然后在不同的访问者者对象中进行不同的操作, 类似于观察者模式, 和观察者模式最大的区别违反了开闭原则和对访问者公布所有细节)
访问者(Visitor)模式是一种对象行为型模式,其主要优点如下。
(1)扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
(2)复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。
(3)灵活性好。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。
(4)符合单一职责原则。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。
访问者(Visitor)模式的主要缺点如下。
(1)增加新的元素类很困难。在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”。
(2)破坏封装。访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性。
(3)违反了依赖倒置原则。访问者模式依赖了具体类,而没有依赖抽象类。
image.png
举例:
apt (annotation processing tools)编译型注解的接口访问者ElementVisitor定义访问的元素是包, 类型, 变量还是参数
15. 中介者模式
中介者模式是一种行为模式, 中介者设计模式旨在是用来多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。(联想到房产中介存在的意义, 协调房东和卖家, 作为桥梁作用)
优点如下:
(1)类之间各司其职,符合迪米特法则。
(2)降低了对象之间的耦合性,使得对象易于独立地被复用。
(3)将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。
缺点:
中介者模式将原本多个对象直接的相互依赖变成了中介者和多个同事类的依赖关系。当同事类越多时,中介者就会越臃肿,变得复杂且难以维护。
举例:
android 中的ServiceManager 和 binder driver, AM, PM 等等
16. 代理模式
代理模式是一种结构性设计模式, 为其他对象提供一个能访问和控制这个对象的方式
优点:
(1)代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
(2)代理对象可以扩展目标对象的功能;
(3)代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性
其主要缺点是:
(1)代理模式会造成系统设计中类的数量增加
(2)在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
(3)增加了系统的复杂度;
举例:
ActivityManagerProxy 作为ActivityManagerService 的代理, 用于和客户端使用的ActivityManager 通信
17. 组合模式
组合模式属于结构型设计模式, 有时又叫作整体-部分模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性
优点:
(1)组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
(2)更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;
缺点是:
(1)设计较复杂,客户端需要花更多时间理清类之间的层次关系;
(2)不容易限制容器中的构件;
(3)不容易用继承的方法来增加构件的新功能;
举例:
android ViewGroup , viewGroup 是有若干的view 或者ViewGroup 组合而成
18. 适配器模式
适配器模式是一种结构性模式,
适配器模式(Adapter)的定义如下:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。
优点:
(1)客户端通过适配器可以透明地调用目标接口。
(2)复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
(3)将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
(4)在很多业务场景中符合开闭原则。
其缺点是:
(1)适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性。
(2)增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。
举例:
listview, recycleview
19. 装饰模式
装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
装饰器模式的主要优点有:
装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
装饰器模式完全遵守开闭原则
其主要缺点是:装饰器模式会增加许多子类,过度使用会增加程序得复杂性。
举例:
contextWraper 和 comtextimpl 的结合使用
20. 享元模式
享元(Flyweight)模式的定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
优点:
相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。
缺点:
(1)为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。
(2)读取享元模式的外部状态会使得运行时间稍微变长。
举例:
应用间通信框架, [应用IPC框架](https://www.jianshu.com/p/288f4e588849)
21. 外观模式
image.png外环模式是一个结构性设计模式, 为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
优点: 1、减少系统相互依赖。 2、提高灵活性。 3、提高了安全性。
缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
举例:
context 是一个典型的外观模式, 内部封装四大组件各式的启动和停止方式, 便于用户使用
第三方框架api 对外均有使用外观设计模式
22. 桥解模式
桥接模式是一种结构设计模式, 桥接设计模式的主要目的是将抽象和实体分离, 使他们可以独立的变化和操作
优点:
(1)抽象与实现分离,扩展能力强
(2)符合开闭原则
(3)符合合成复用原则
(4)其实现细节对客户透明
缺点:
(1)由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,能正确地识别出系统中两个独立变化的维度,这增加了系统的理解与设计难度。
举例:
window 和 WindowManager(实现个体)WindowManagerImpl(实现逻辑), activity 和 ActivityManager(个体),ActivityManagerImpl (逻辑)
23. 单例模式
单例模式创建型模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点
设计模式分类
参考文档
https://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html