描述如何将类、对象结合组成更大的结构
类的结构模式:继承父类并实现接口,如适配器
对象的结构模式:将不同类型的对象组合在一起
填平“既有内容”和“需要结果”之间的落差。
修改时可以不必修改既有的类,用于不方便修改原有类,如只有class文件,程序是公有包等
Target:定义“需求结果”需要的接口,如22V电压
Client: 使用“需求结果”的类,如笔记本
Adaptee:既有内容的类,如220V电压
Adapter:负责转换的类,实现Target接口,持有或继承Adaptee,如变压器
1) 先编写client端;在编写中抽取Target接口;
2) 如果不需要使用Adaptee的protected方法,则使用委托,否则继承
装饰模式:不能改变原有类的接口
缺省适配器模式:为接口的方法提供缺省实现
本身是树状结构的数据结构就相当于Composite pattern。如目录,容器等
Leaf:表示“叶子”,不可放入任何东西
Composite:表示“树枝”,可放入Leaf和Composite,持有Component的引用
Component:是Leaf和Composite共同的父类。
Client:持有Component引用,对Leaf和Composite一视同仁
分为安全式和透明式,如果把add,remove等管理方法放在Component中,则为透明式;否则放入Composite则为安全式,Composite可以在继承Component的基础上,实现Compositable接口,该接口定义add remove get等方法 ,从重构的角度,个人倾向于安全式。
命令模式:用于命令类的合成上,由几个命令类合成为宏命令
迭代模式:常使用迭代模式遍历Composite对象
责任链模式:责任链通常会用到树上
享元模式:复合享元对象是树枝对象,单纯享元是树叶对象
在对象上不断披上decoration。
Decorator继承自Component是为了对装饰和内容一视同仁。
以对客户端透明的方式扩展客户的行为
Component:抽象接口,在蛋糕比喻中,相当于装饰前的蛋糕
ConcreteComponent:具体的蛋糕
Decorator:抽象类,实现Component,持有Component的引用
ConcreteDecorator:实现Decorator,构造函数 newDecorator(Component com) 传入引用。具体的装饰,如抹上奶油的蛋糕
动态给一个对象增加功能,而且该功能还可以撤销(就是没有写死在对象所在的类)
增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实
1.装饰模式比继承灵活,因为是动态的
2.排列组合,可以创造很多不同的行为
1.动态组合意味着比继承更容易出错,如循环引用
尽量保持Component是一个轻类
如果只有一个ConcreteDecorator,则可以将Decorator和ConcreteDecorator合并
在实际中,Decorator或 ConcreteDecorator 需要增加新的方法,当客户端需要使用使用这些新方法时,声明ConcreteDecorator com,如果不用到新方法,仍然使用 Component com; 扩展Component接口的装饰模式称为半透明的装饰模式,介于装饰模式和适配器模式之间,不过要考虑用意:是否修改接口,Adapter改变接口,不变功能,装饰者不变接口,改变功能;半透明两个都变
输入和输出、char和byte的对称。 Reader InputStream Writer OutputStream
InputStream:共11个类, 有7个直接子类,其中子类FilterInputStream又有4个子类。可以分为原始流和链接流两种类型。
原始流接受 File Piped ByteArray StringBuffer(接收String) 。
链接流:
FilterInputStream以另一个输入流为流源,BufferInputStream 缓存功能,DataInputStream 原始类型提供多字节,LineNumberInputStream 提供行计数功能,可以按照行号读入数据,PushbackInputStream提供特殊功能,将读取的数据再推入到InputStream,
ObjectInputStream 完成对象的串行化,
SequenceInputStream组合多个输入流。 原始流作为Component,链接流作为Decorator。
OutputStream类似于InputStream ,有8个子类,3个是原始流ByteArrayOutputStream, FileOutputStream,PipiedOutputStream, 5个是链接流 BufferOutputStream FilterOutputStream (DataOutputStream PrintStream BufferOutputStream 三个子类) 其子类PrintStream对要输出的数据格式化,可以重载该类的print 和println 两个方法
Reader 有四个原始流 CharArray InputStreamReader (FileReader) PipedReader StringReader, 4个链接流BufferReader(LineNumberReader)和FilterReader(PushbackReader)
Writer和Reader对称
InputStream中的链接流是半透明的
BufferReader中的readLine() 方法
InputSteam中的 InputStreamReader 将InputStream适配为Reader, OutputStream则正相反
原始对象访问比较费时,如图像的加载
控制对原始对象的访问,如Reflection方式
虚拟代理:realObject消耗较多资源时如图像,延迟加载
远程代理:realObject不在本机上
智能引用代理:realObject使用时,提供额外操作,比如记录调用次数等
保护代理:控制对realObject的使用,对不同的人提供不同的权限
Subject:规定Proxy和RealSubject一视同仁的接口。供Client使用。
Proxy: 持有RealSubject的引用,用于在RealSubject执行前后执行某种操作,控制对RealObject的访问。
RealSubject:当代理不能处理时,就要RealSubject上场。
Client:利用代理模式的程序。
动态 创建对象、调用方法
远程代理:对客户端隐藏网络连接的细节
虚拟代理:必要时候加载realObject
保护代理:运行时候检查访问权限
智能引用代理:执行额外处理
适配器模式:是否改变Subject的接口
装饰模式:代理模式对对象的使用进行控制,装饰模式提供功能的增强。 功能不同(控制访问和扩展功能),关系实现(编译期静态确定,运行期动态构造)
门面模式:门面可能会兼职代理职责
尽量共享对象实例,不做无谓的new。
在创建共享对象的部分,要使用synchronized
对象种类有限,且是不变对象
对象信息可共享
Flyweight:公共接口,不能共享的以参数传入
ConcreteFlywight:
FlyweightFactory:产生Flyweight的工厂,可使用hashmap存放已创建的对象。
Client:利用FlyweightFactory产生Flyweight对象
单纯享元
复合享元:Flyweight是合成模式
1. 区分那些信息共享,那些不共享,共享的存储在Flyweight中,不能共享的由Client传入
2. 对象实例放入hashmap中,不会被垃圾回收,不在使用时,将hashmap对应项置空。
屏蔽系统内错综复杂的关系,提供给外部一个简单且高级的接口
减少子系统和客户端、其他子系统的耦合性
Façade:给外部提供较高级且单一的接口,根据用户的不同,包含不同的子系统部分
SubSystem: 一组功能相关的类
Client:利用FaçadePattern的类
Facade在系统中每种只需要一个
功能类层次:子类扩展父类的功能,如苹果和红苹果的关系
实现类层次:父类规定接口,子类来实现
为什么要将“功能类”和“实现类”一分为二?
为了独立演化。 新增类时先判断是功能还是实现,如果需要新增功能类,则只要对功能类扩充,新功能可使用已存在的实现,如果需要新增实现类,例如同样的功能要在window , os ,linux下实现,只要对implementor进行三种扩展。
将功能类和实现类进行解耦(通过组合而不是继承进行关联)
实现类的改变对功能类完全是透明的(通过spring注入可以实现)
Abstraction:位于“功能类”的最上层,在构造函数中,传入implementor的实例
RefineAbstraction:功能类的扩展和修正,一般extendsAbstraction
Implementor:位于“实现类”的最上层,规定接口的API
ConcreteImplementor:Implementor的具体实现.
通常情况,Implementor和Abstraction中方法不一样,Implementor主要提供底层接口,Abstraction是基于这些接口的更高一层的操作。
尽量在Abstraction中与Implementor交互,不涉及子类。
继承其实就是对可变性的封装,抽象类稳定,子类封装变化。一种继承不应该处理两种变化,如果这两种变化彼此是独立的,这就是桥梁模式显身手的地方。
如果出现两个以上的变化因素,就要找出那个是静态的,使用继承实现,那个是动态的使用组装实现。
桥梁模式 是对继承和组装使用的一个很好的例子
策略模式:用意不同,桥梁是为了抽象化和实现化解耦,策略是算法的不同实现;策略只有一种变化
装饰模式:桥梁的抽象化子类不能像装饰模式那样嵌套
状态模式:状态描述对象和其状态的关系;桥梁描述两个等级结构的关系。状态可以看做是桥梁退化的特殊情况。
抽象工厂模式:抽象工厂为桥接模式提供产品创建的结构; 抽象工厂是子类和子类打交道
Implementor只有一种实现,则Implementor可以去掉
不同的RefineAbstraction可使用同一个ConcreteImplementor