对象结构型模式
结构型模式(Structural Pattern)描述如何将类或者对象结合在一起形成更大的结构
适配器模式
在适配器模式中可以定义一个包装类,包装不兼容接口的对象,这个包装类指的就是适配器(Adapter),它所包装的对象就是适配者 (Adaptee),即被适配的类。适配器提供客户类需要的接口,适配器的实现就是把客户类的请求 转化为对适配者的相应接口的调用。适配器可以使由于接口不兼容而不能交互的类可以一起工作。这就是适配器模式的模式动机。
简单的说,需要实现一个接口,这个接口的功能已经有一个类实现,但这个类却不符合接口的规则,因此使用适配器Adapter包装适配者Adaptee(可以有多个Adaptee),调用Adaptee的方法进行二次封装到Adapter的方法中,使用者调用Adapter的方法,并不关心适配器如何实现,反正Adapter对外能够提供功能即可
模式定义 :适配器模式(Adapter Pattern) :将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作。
适配器的核心在于使用新的类实现旧接口,老接口不能轻易动,新的实现类不符合老接口的规则,因此使用适配器实现老接口,调用新类的方法,相当于对各种实现类进行统合,对外能够通过统一的旧接口提供功能。
Outlet提供电压,AC plug插不进去,使用Adapter进行中间转化,使用者可以利用多态使用AC plug返回一个Adapter,Adapter调用Outlet提供电压。
适配器模式有三种实现方式:
类适配器
Adapter继承功能类实现老接口,通过super调用方法
@Configuration
public class SpringConfiguration {
@Bean
public Outlet220V outlet220V(){
return new Outlet220V();
}
@Bean(name="adapterA")
public AdapterA adapterA(){
return new AdapterA();
}
}
public interface Outlet5V {
//提供5V电压
int outlet5V();
}
//新的实现类,能提供220V电压
public class Outlet220V {
public int outlet220V(){
System.out.println("我被适配器调用,我能输出220V电压");
return 220;
}
}
//类适配器
public class AdapterA extends Outlet220V implements Outlet5V {
@Override
public int outlet5V(){
System.out.println("我是类适配器,继承实现类,实现老接口");
return super.outlet220V()/44;
}
}
public class AdapterPatternTest {
public static void main(String[] args){
ApplicationContext context= new AnnotationConfigApplicationContext(SpringConfiguration.class);
Outlet5V outlet5V=(AdapterA)context.getBean("adapterA",AdapterA.class);
outlet5V.outlet5V();
}
}
对象适配器
内部维护实现对象,调用实现方法实现老接口:
public class AdapterB implements Outlet5V{
private Outlet220V outlet220V=new Outlet220V();
public int outlet5V(){
System.out.println("我是对象适配器,内部维护功能对象,调用实现方法实现老接口");
return outlet220V.outlet220V()/44;
}
}
接口适配
介绍完类适配器和对象适配器,我们再来看看接口适配器,接口适配器相对类适配器和对象适配器而言,接口适配器相对更加灵活,就好比手机适配器中的万能适配器,不管接入的是多少伏的电源,最终都能保证输出电源为5V。
首先,定义一个总的抽象类,并且给予一个默认值(或者直接是接口,目的都是为了定义功能),即提供总的抽象
public abstract class AbstractAdapter {
public int output(){
return 220;
}
}
基于该抽象类重写方法,提供不同的功能
public class Outlet110V extends AbstractAdapter {
@Override
public int output(){
return 110;
}
}
public class Outlet440V extends AbstractAdapter {
@Override
public int output(){
return 440;
}
}
适配器内部维护一个总的抽象对象,提供不同的构造器,提供setter,实现老接口时,必须能判断当前维护的抽象对应的具体实现是哪一个,可使用instanceof或者反射
public class AdapterC implements Outlet5V {
private AbstractAdapter abstractAdapter;
public AdapterC(AbstractAdapter abstractAdapter){
this.abstractAdapter=abstractAdapter;
}
//这里是接口适配器,内部维护总的抽象,可以是接口,也可以是抽象类,对外提供方法,因此必须有办法判断
//具体是哪一个实现,可使用instanceof,也可以使用反射读取信息
@Override
public int outlet5V(){
System.out.println("我是接口适配器,内部维护一个总抽象,根据instanceof判断当前是哪一个实现");
if(abstractAdapter instanceof Outlet110V)return abstractAdapter.output()/22;
else if(abstractAdapter instanceof Outlet440V)return abstractAdapter.output()/88;
return 5;
}
}
桥接模式
将抽象部分与它的实现部分分离,使它们都可以独立地变化。将抽象化(Abstraction)与实现化 (Implementation)脱耦,使得二者可以独立地变化。
假设有两个接口A与B,A有6个具体实现,B有4个具体实现,现在必须组合A,B以提供组合式的更强的功能,共有6*4=24个具体提供,为实现解耦,现在将某一个接口抽象化,将A变为抽象类,内部维护一个B并提供setter,A的具体实现都要继承A,因为A内部维护一个B并提供setter,因此A不关心具体的B是哪一个,调用功能即可,只需6+4=10个具体提供。
模式结构 :
• Abstraction:抽象类,内部维护一个Implementor并提供setter
• RefinedAbstraction:扩充抽象类
• Implementor:实现类接口
• ConcreteImplementor:具体实现类
抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
• 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
• 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增 加的系统,桥接模式尤为适用。
//实现接口与具体实现
public interface VideoStream {
public void videoStream();
}
public class AVIVideoStream implements VideoStream {
@Override
public void videoStream(){
System