通过组合类和对象产生更大结构以适应更高层次的逻辑需求
适配器模式(Adapter Pattern)
Convert the interface of a class into another interface clients expect.Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.(将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作)
角色
Target目标角色
该角色定义把其他类转换为何种接口,也就是我们的期望接口
Adaptee源角色
你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象,经过适配器角色的包装,它会成为一个崭新、靓丽的角色
Adapter适配器角色
适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:把源角色转换为目标角色,转换方式:通过继承或是类关联的方式
优点
- 适配器模式可以让两个没有关系的类在一起运行
- 增加了类的透明性
- 提高了类的复用性
- 灵活性非常好
实现分类
类适配器模式
在需要不改变(或者由于项目原因无法改变)原有接口或类结构的情况下扩展类的功能以适配不同的接口时,可以使用类的适配器模式
适配器模式通过创建一个继承原有类(需要扩展的类)并实现新接口的适配器类来实现
对象适配器模式
对象适配器模式的思路与类适配器模式基本相同,只是修改了Adapater类。Adapater类不再继承Source类,而是持有Source类的实例,以解决兼容性问题
接口适配器模式
在不希望实现一个接口中所有的方法时,可以创建一个抽象类AbstractAdapter实现所有方法,在使用时继承该抽象类按需实现方法即可
装饰器模式(Decorator Pattern)
Attach additional responsibilities to an object dynamically keeping the same interface.Decorators providea flexible alternative to subclassing for extending functionality.(动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活)
角色
Component抽象构件
Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象
ConcreteComponent 具体构件
ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是它
Decorator装饰角色
一般是一个抽象类,做什么用呢?实现接口或者抽象方法,它里面可不一定有抽象的方法呀,在它的属性里必然有一个private变量指向Component抽象构件
具体装饰角色ConcreteDecorator
具体的装饰类,你要把你最核心的、最原始的、最基本的东西装饰成其他东西
优点
- 装饰类和被装饰类可以独立发展而不会相互耦合
- 装饰模式是继承模式的一种替代方案
- 装饰模式可以动态的扩展一个类的功能
缺点
多层的装饰是比较复杂的
适用场景
- 需要扩展一个类的功能,或者给一个类增加一个附加功能
- 需要动态地给一个对象增加功能,这些功能可以再动态地撤销
- 需要为一批的兄弟类进行改或添加功能,首选装饰模式
装饰器模式包括Source和Decorator两种角色,Source是被装饰者,Decorator是装饰者。装饰器模式通过装饰者可以为被装饰者动态地添加一些功能
代理模式(Proxxy Pattern)
Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供一种代理以控制对这个对象的访问)
代理模式也叫做委托模式,它是一项基本设计技巧。许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式
角色
Subject抽象主题角色
抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求
RealSubject具体主题角色
也叫做被委托角色、被代理角色。它才是冤大头,是业务逻辑的具体执行者
Proxy代理主题角色
也叫做委托类、代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作
优点
- 职责清晰
- 高扩展性
- 智能化
扩展
普通代理
要求就是客户端只能访问代理角色,而不能访问真实角色
强制代理
只有通过真实角色指定的代理类才可以访问,也就是说由真实角色管理代理角色
动态代理
动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象
门面模式(Facade Pattern)
也叫外观模式
Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystem easier to use.(要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用)
门面模式注重“统一的对象”,也就是提供一个访问子系统的接口,除了这个接口不允许有任何访问子系统的行为发生
客户端无需关心和知晓系统内部各子模块(系统)之间的复杂关系,其主要目标是降低访问拥有多个子系统的复杂系统的难度,简化客户端与其之间的接口
外观模式将子系统中的功能抽象成一个统一的接口,客户端通过这个接口访问系统,使得系统使用起来更加容易,简单地说,门面对象是外界访问子系统内部的唯一通道
角色
Facade门面角色
客户端可以调用这个角色的方法。此角色知晓子系统的所有功能和责任。一般情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去,也就说该角色没有实际的业务逻辑,只是一个委托类
subsystem子系统角色
可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。子系统并不知道门面的存在。对于子系统而言,门面仅仅是另外一个客户端而已
优点
- 减少系统的相互依赖
- 提高了灵活性
- 提高安全性
缺点
门面模式最大的缺点就是不符合开闭原则,对修改关闭,对扩展开放
适用场景
- 为一个复杂的模块或者子系统提供一个供外界访问的接口
- 子系统相对独立–外界对子系统的操作黑箱操作即可
- 预防低水平人员带来的风险扩散
桥接模式(Bridge Pattern)
Decouple an abstraction from its implementation so that the two can vary independently.(将抽象和实现解耦,使得两者可以独立地变化)
桥接模式主要用于解决在需求多变的情况下使用继承造成类爆炸的问题,扩展起来不够灵活
可以通过桥接模式将抽象部分与实现部分分离,使其能够独立变化而相互之间的功能不受影响
具体做法是通过定义一个桥接接口,使其实现类的功能独立于接口实现类,降低它们之间的耦合度
角色
抽象化角色 Abstraction
它的主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用,该角色一般是抽象类
实现化角色 Implementor
它是接口或者抽象类,定义角色必需的行为和属性
修正抽象化角色 RefinedAbstraction
它引用实现化角色对抽象化角色进行修正
具体实现化角色 ConcreteImplementor
它实现接口或抽象类定义的方法和属性
优点
- 抽象和实现分离
- 优秀的扩充能力
- 实现细节对客户透明
适用场景
- 不希望或不适用继承的场景
- 接口或抽象类不稳定的场景
- 重用性要求较高的场景
组合模式(Composite Pattern)
Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.(将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性)
又叫部分整体模式,主要用于实现部分和整体操作的一致性。组合模式通常根据树形结构来表示部分及整体之间的关系,使得用户对单个对象和组合的对象的操作具有一致性
角色
Component抽象构件角色
定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性
Leaf叶子构件
叶子对象,其下再也没有其他的分支,也就是遍历的最小单位
Composite树枝构件
树枝对象,它的作用是组合树枝节点和叶子节点形成一个树形结构
优点
- 高层模块调用简单
- 节点自由增加
适用场景
- 维护和展示整体-部分关系关系的场景,如树形菜单、文件和文件夹管理
- 从一个整体中能独立出部分模块或功能的时候
组合模式通过特定的数据结构简化了部分和整体之间的关系,使得客户端可以像处理单个元素一样来处理整体的数据集,而无须关心单个元素和整体数据集之间的内部复杂关系
组合模式以类似树形结构的方式实现整体和部分之间关系的组合
享元模式(Flyweight Pattern)
Use sharing to support large numbers of fine-grained objects efficiently.(使用共享对象可有效地支持大量的细粒度的对象)
要求细粒度对象,那么不可避免地使得对象数量多且性质相近,那我们就将这些对象的信息分为两个部分:内部状态(intrinsic)与外部状态(extrinsic)
- 内部状态
指对象可以共享出来的信息,存储在享元对象内部并且不会随环境变化而变化,它们可以作为一个对象的动态附加信息,不必直接存储在某个对象中,属于可共享的部分
- 外部状态
是对象得以依赖的一个标记,是随环境改变而改变的、不可以共享的状态,它是一批对象的统一标识,是唯一的一个索引值
角色
抽象享元角色(FlyWeight )
它简单地说就是一个产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现
抽象享元角色一般为抽象类,在实际项目中,一般是一个实现类,它是描述一类事物的方法。在抽象角色中,一般需要把外部状态和内部状态(当然了,可以没有内部状态,只有行为也是可以的)定义出来,避免子类的随意扩展
具体享元角色(Concrete Flyweight)
具体的一个产品类,实现抽象角色定义的业务。该角色中需要注意的是内部状态处理应该与环境无关,不应该出现一个操作改变了内部状态,同时修改了外部状态,这是绝对不允许的
不可共享的享元角色( unshared Concrete Flyweight)、
不存在外部状态或者安全要求(如线程安全)不能够使用共享技术的对象,该对象一般不会出现在享元工厂中
享元工厂(FlyWeight Factory)
职责非常简单,就是构造一个池容器,同时提供从池中获得对象的方法
** 享元模式的目的在于运用共享技术,使得一些细粒度的对象可以共享,我们的设计确实也应该这样,多使用细粒度的对象,便于重用或重构**
优缺点
享元模式是一个非常简单的模式,它可以大大减少应用程序创建的对象,降低程序内存的占用,增强程序的性能,但它同时也提高了系统复杂性,需要分离出外部状态和内部状态,而且外部状态具有固化特性,不应该随内部状态改变而改变,否则导致系统的逻辑混乱
适用场景
- 系统中存在大量的相似对象
- 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定的身份
- 需要缓冲池的场景
过滤器模式(Filter/Criteria Pattern)
**
结构模式比较
代理模式VS装饰模式
共同点
都具有相同的接口
不同点
代理模式着重对代理过程的控制,而装饰模式则是对类的功能进行加强或减弱,它着重类的功能变化
- 代理模式是把当前的行为或功能委托给其他对象执行,代理类负责接口限定,是否可以调用真实角色,以及是否对发送到真实角色的消息进行变形处理,它不对被代理角色的功能做任何修改
- 装饰模式是在要保证接口不变的情况下加强类的功能,它保证的是被修饰对象功能比原始对象丰富(也可以是减弱),但不做准入参数判断和准入条件过滤
装饰模式VS适配器模式
相似点
都是包装作用,都是通过委托方式实现功能
不同点
装饰者模式包装的是自己的兄弟类,隶属于同一个家族(接口或父类),适配器模式则修饰非血缘关系的类,把一个非本家族的类伪装成本家族的类,但它的本质还是非相同接口的对象
意图不同
装饰者模式的意图是加强类的功能,而适配器模式关注的是转化,它的意图主要是两个不同对象之间的转化
施与对象不同
装饰者模式装饰的对象必须是自己的同宗,也就是相同的接口或者父类,只有在相同的行为和属性的情况下,才能比较行为是增强还是减弱;适配器模式则必须是两个不同的对象,因为它着重于转换,只有两个不同的对象才有转换的必要
场景不同
装饰模式在任何时候都可以使用,只要是想增强类的功能,而适配器模式则是一个补救模式,一般出现在已成熟的项目或者已经构建完毕的项目中,作为一个紧急处理手段来使用
扩展性不同
装饰者模式很容易扩展