一、代理模式
一、概念
代理模式就是给一个对象提供一个代理,并由代理对象控制对原对象的引 用。它使得客户不能直接与真正的目标对象通信。代理对象是目标对象的代表, 其他需要与这个目标对象打交道的操作都是和这个代理对象在交涉。
例如:去4s店买车。
二、优点
代理模式将目标对象与客户端分离 ,起中介和保护目标对象作用,降低了耦合度。
扩展目标对象功能。
三、代理模式结构
四、代理模式分类
代理模式分为静态代理与动态代理。
一、静态代理
静态代理模式的特点,代理类接受一个 Subject 接口的对象,任何实现该接 口的对象,都可以通过代理类进行代理,增加了通用性。
优点:
可以做到在符合开闭原则的情况下对目标对象进行功能扩展。
缺点:
一个代理类只能代理一个接口,工作量太大;代理类是运行前编码已 经完成的;必须先有接口,再有代理;接口一旦发生变量,代理类也要修改。
二、动态代理
在动态代理中我们不再需要再手动的创建代理类,我们只需要编写一个动态 处理器就可以了。真正的代理对象在运行时为我们动态的来创建。
动态代理分为jdk代理和cglib代理。
1.jdk代理
是通过反射来实现的,借助 Java 自带的java.lang.reflect.Proxy,通过固定的规则生成。
jdk代理实现方法:
1. 编写一个委托类的接口,即静态代理的
2. 实现一个真正的委托类,即静态代理的
3. 创建一个动态代理类,实现 InvocationHandler 接口,并重写该 invoke 方法
4. 在测试类中,生成动态代理的对象。
总结:
虽然相对于静态代理,动态代理大大减少了我们的开发任务,同时减少了 对业务接口的依赖,降低了耦合度。但是它始终无法摆脱仅支持 interface 代理的桎梏,只能对接口进行代理。
2.cglib代理
CGLib 采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建 子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切 逻辑。
Cglib 代理实现方法:
1.需要引入 cglib 的 jar 文件,但是 Spring 的核心包中已经包括了 Cglib 功能,所 以直接引入 spring-core-xxx.jar 即可.
2.引入功能包后,就可以在内存中动态构建子类
3.代理的类不能为 final,否则报错
4.目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额 外的业务方法.
总结:
CGLIB 创建的动态代理对象比JDK 创建的动态代理对象的性能更高,但是 CGLIB 创建代理对象时所花费的时间却比 JDK 多得多。所以对于单例的对象,因为无需频繁创建对象,用 CGLIB 合适,反之使用 JDK 方式要更为合适一些。同时由 于 CGLib 由于是采用动态创建子类的方法,对于 final 修饰的方法无法进行代理。
二、适配器模式
定义:
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容 而不能一起工作的那些类能一起工作。
适配器模式(Adapter)包含以下主要角色:
目标(Target):当前系统业务所期待的功能,它可以是抽象类或接口,相当于 欧标插座。
适配者(Adaptee):需要被适配的对象或类型,相当于标准插头。
适配器(Adapter):连接目标和源的中间对象,相当于插头转换器。
实现方式:
适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中, 该类同时实现当前系统的业务接口。
三、模板方法模式
程序开发中,有些实现步骤流程时固定的,可以抽取父类,在父类中实现各个步骤,再在父类中定义一个流程控制方法,在此方法中按照步骤调用执行,可以将某个容易发生变化的步骤定义为抽象方法,针对不同情况,可扩展一个子类实现抽象方法,最终由子类对象调用父类中流程控制方法即可。
定义
定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类 可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
模板方法(Template Method)模式包含以下主要角色:
抽象类:负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法 构成。
模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。
抽象方法:一个抽象方法由抽象类声明、由其具体子类实现。
具体方法:一个具体方法由一个抽象类或具体类声明并实现,其子类可 以进行覆盖也可以直接继承。
具体子类:实现抽象类中所定义的抽象方法,它们是一个组成步骤。
优点:
提高代码复用性,将相同部分的代码放在抽象的父类中,而将不同的代码放 入不同的子类中。 实现了反向控制,通过一个父类调用其子类的操作,通过对子类的具体实现 扩展不同的行为,实现了反向控制 ,并符合“开闭原则”。
缺点:
对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加 庞大,设计也更加抽象。 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,它提高 了代码阅读的难度。
四、策略模式
可以将同一种功能不同实现细节先抽取一个抽象接口/抽象类。然后把不同的实现让子类。
定义
该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算 法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法 进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这 些算法进行管理。
策略模式的主要角色如下:
抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。 此角色给出所有的具体策略类所需的接口。
具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的 算法实现或行为。
环境(Context)类:持有一个策略类的引用,最终给客户端调用。
优点:
策略类之间可以自由切换,由于策略类都实现同一个接口,所以使它们之间可以 自由切换。 易于扩展,增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改 变原有的代码,符合“开闭原则“, 避免使用多重条件选择语句(if else),充 分体现面向对象设计思想。
五、观察者模式
定义:
又被称为发布-订阅(Publish/Subscribe)模式,它定义了一种一对多的依 赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化 时,会通知所有的观察者对象,使他们能够自动更新自己。
在观察者模式中有如下角色:
抽象主题(抽象被观察者):抽象主题角色把所有观察者对象保存在一个集合里, 每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除 观察者对象。
具体主题(具体被观察者):该角色将有关状态存入具体观察者对象,在具体主 题的内部状态发生改变时,给所有注册过的观察者发送通知。
抽象观察者:是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改 通知时更新自己。
具体观察者:实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新 自身的状态。
优点:
降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。 被观察者发送通知,所有注册的观察者都会收到信息【可以实现广播机制】。