设计模式
这是比较简单的介绍,从Android源码设计模式这本书里面抄的笔记加上自己的一点理解,如果想看详细一点的,可以直接点下面的链接:
ListView适配器模式的应用
ListView观察者模式的应用
AsyncTask模板模式的应用
ListView桥接模式的应用
Iterator – 迭代器模式(游标模式)
定义:行为型设计模式之一,源于对内容的访问,比例Java中的List、Map、数组等,旨在提供一种方法顺序访问一个容器对象中的各个元素,而又不需要暴露该对象的内部表示。
使用场景:遍历一个容器对象时
UML类图:
关系说明:
- Iterator:迭代器接口,负责定义、访问和遍历元素的接口
- ConcreteIterator:具体迭代器类,实现迭代器接口,并记录遍历的当前位置
- Aggregate:容器接口,负责提供创建具体迭代器角色的接口(重点在iterator方法,将两个接口关联 )
- ConcreteAggregate:具体容器类,具体迭代器角色与该容器相关联
优点:支持以不同的方式去遍历一个容器对象,也可以有多个遍历,弱化了容器类与遍历算法之间的关系
缺点:对类文件的增加
源码:List、Map等
思想: 数据的增删改查,和遍历属于不同的职能,如果都写在相同的类中违背了单一职责原则,所以这里利用迭代器模式来实现遍历功能,然后原有的类关联相应的迭代器,起到解耦的功能,又不用开发者自己去实现
Decorator – 装饰者模式(包装模式)
定义:结构型设计模式之一,使用一种对客户端透明的方式来动态扩展对象的功能,它是继承关系的一种替代方案。简单来说就是动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
使用场景:需要动态且透明地扩展类的功能时
UML类图:
关系说明:
- Component:抽象组件,可以是一个接口或者抽象类,充当被装饰的原始对象
- ConcreteComponent:组件具体实现类,装饰的具体对象
- Decorator:抽象装饰者,职责为装饰我们的组件对象,其内部维护一个指向组件对象的引用。在大多数情况下为抽象类,根据不同需求实现不同子类,如果装饰逻辑单一,只有一个的情况下也可省略直接使用具体装饰者
- ConcreteDecoratorA:装饰者具体实现类A,对抽象装饰者作出具体的实现
- ConcreteDecoratorB:装饰者具体实现类B,对抽象装饰者作出具体的实现
源码: Context(抽象组件)、ContextImpl(具体组件)、ContextWrapper(抽象装饰者)、Activity(具体装饰者)等
思想:一种对原有功能的扩展,可以替代继承,更灵活
注意:和代理模式的区别:
- 装饰者模式是以对客户端透明的方式扩展对象的功能,是继承关系的一种替代方案;而代理模式则是给一个对象提供一个代理对象,并由代理对象来控制对原有的引用
- 装饰者模式应该为所装饰的对象增强功能;代理模式对所代理的对象施加控制,但不对对象本身的功能进行增加
Flyweight – 享元模式
定义:享元模式是对象池的一种实现,用来尽可能减少内存使用量,它适合用于可能存在大量重复对象的场景,来缓存可共享的对象,达到对象共享,避免创建过多对象的效果,从而提升性能、避免内存的移除。享元模式中的享元对象包含两种状态:内部状态(可以共享的状态,不会随着环境变化),外部状态(不可共享,会变化),一般在享元模式中会建立一个对象容器,经典实现为Map,以内部状态为key,享元对象为value。
使用场景:存在大量重复对象的场景、需要缓存池的场景
UML类图:
关系说明:
- Flyweight:享元对象抽象基类或者接口
- ConcreteFlyweight:具体的享元对象
- FlyweightFactory:享元工厂,负责管理享元对象池和创建享元对象
优点:可以大大减少应用程序创建的对象,降低程序内存的占用,增强程序的性能
缺点:
- 使系统更加复杂。为了使对象可以共享,需要将一些状态外部化。
- 读取外部化状态使得运行时间稍微边长。
源码:String(使用字面值字符串来创建字符串)、Handler消息机制中Message(同时充当三个角色)对象的获取
思想:一种缓存思想,在面临大量重复相似的对象创建时可以使用,提升性能
Facade – 外观模式(门面模式)
定义:要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行
使用场景:
- 为一个复杂子系统提供一个简单接口
- 当需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点
UML类图:
关系说明:
- Facade:系统对外的统一接口,系统内部系统地工作中
- SystemA、SystemB:子系统接口
优点:
- 对客户程序隐藏子系统细节,因而减少了客户对于子系统的耦合,能够拥抱变化
- 外观类对子系统的接口封装,使得系统更易于使用
缺点:
- 外观类接口膨胀。API接口较多,在一定程度上增加了用户使用成本
- 没有遵循开闭原则,当业务出现变更的时候,可能需要直接修改外观类
源码:ContextImpl(外观类)
思想:对多层系统进行封装,提供统一访问入口,降低使用成本
Template – 模板方法模式
定义:当遇到一个问题,我们知道解决该问题所需的关键步骤,并确定了这些步骤的执行顺序,但是,某些步骤的具体实现是未知的,这类问题的解决方案就是–模板方法模式。简单来说就是:流程封装
使用场景:
- 多个子类有公有的方法,并且逻辑基本相同
- 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现
- 重构时经常使用,把相同的代码抽取到父类中,然后通过钩子函数约束其行为
UML类图:
关系说明:
- AbsTemplate:抽象类,定义了一套具体的(算法)框架。执行步骤为final(execute方法),但是每一个步骤的具体实现由子类根据需求可以重写
- ConcreteImplA:具体实现类A
- ConcreteImplB:具体实现类B
优点:
- 封装不变部分,扩展可变部分
- 提取公共部分代码,便于维护
缺点:
提升代码阅读的难度,不利于理解
<