java模式笔记 (四)—— 结构模式

 描述如何将类、对象结合组成更大的结构

    类的结构模式:继承父类并实现接口,如适配器

    对象的结构模式:将不同类型的对象组合在一起

适配器

作用:

    填平“既有内容”和“需要结果”之间的落差。

    修改时可以不必修改既有的类,用于不方便修改原有类,如只有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改变接口,不变功能,装饰者不变接口,改变功能;半透明两个都变

IO库:

    输入和输出、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

你可能感兴趣的:(java模式笔记 (四)—— 结构模式)