适配器模式:经典的入门模式,顾名思义,最主要的目的是达到适配(网上结构图很多,自己找一下,懒得放进来)
1:什么是适配?为什么需要适配?
1)生活中的案例
case 1:美国的电压标准为110V,而国内是220V。在美国买一个家用电器,在国内不能正常使用,电压不同电器会受到损害。怎么办呢?收购一个适配器,适配器连接中国电源,美国电器再连接适配器,这样就可以正常使用了
case 2:床头只安装了三相插孔(坑爹的装修师傅),但我们的手机不能用(手机一般是两孔的),怎么办呢?买一个三相到两相的转换器,转换器连接电源,手机插入转换器,一切都搞定了
2)代码世界中的案例
step 1:
公司代码中有一个类Adaptee,这个类自编写之初就勤勤恳恳的工作着,在这个类中有一个方法
//用了10年了
//99个地方在调用该类中的doSomething1 这个方法
public void doSomething1(){
//忽略这句简单的话,这个方法中其实有10000多行代码,调用无数别人的接口
System.out.println("do doSomething1.......");
}
我们亲切的称呼这个类为源类
step 2:
doSomething1这个方法一直用的好好的(并且我们知道在99个地方调用它),现在在第100个地方(员工张三的工作)需要调用Adaptee我们的源类了,但是我们悲催的发现,这个类中的方法已经不够我们去用了,因为公司新收购的子公司为我们提供了一个新的方法doSomething2
问题分析
1:张三需要去调用原类中的doSomething1
2:除了调用原类中的doSomething1方法,还需要调用新的doSomething2
解决方案
在原类中新加入新的方法,还是调用原类
问题所在
有可能加入新的方法(doSomething2)的时候破坏了原来的方法(doSomething1)让以前正确使用位置的代码不能正常工作了
而且其他调用位置压根不需要新的方法,这就很浪费了,怎么办呢?
最终解决方案:
1:编写一个接口Target(目标接口)
public interface Target {
public void doSomething2();
}
在这里定义了新的方法
2:编写适配器类
public class Adapter extends Adaptee implements Target{
@Override
public void doSomething2() {
// TODO Auto-generated method stub
//直接调用别人的方法
System.out.println("do doSomething2.......");
}
}
这个二合一的类即继承了源类(为了获取doSomething1)而且实现了Target接口(为了兼容doSomething2)
最后我们工作的时候
//Adaptee a1=new Adaptee() 不要使用它了,因为它只有doSomething1这个方法,不符合我们的需求
Adapter a=new Adapter();//包含了两个方法,是我们所需要的
a.doSomething1();
a.doSomething2();
这样,我们在没有修改的前提下,完成了新功能的拓展(这句话有点眼熟啊)
刚才我们完成的就是所谓的类的适配模式,我们现在再来看看另外一种适配模式:对象的适配模式
改起来很简单
回想下刚才我们的适配器类是这样的
public class Adapter extends Adaptee implements Target
继承源类,实现目标接口。但是、但是我们java是单继承的,如果还需要有别的类要继承的话,这种模式就废了
对象的适配模式就是为了解决这个问题
public class Adapter2 implements Target{
private Adaptee adaptee;
public Adapter2(Adaptee adaptee) {
super();
this.adaptee = adaptee;
}
@Override
public void doSomething2() {
// TODO Auto-generated method stub
//直接调用别人的方法
System.out.println("do doSomething2.......");
}
public void doSomething1(){
adaptee.doSomething1();
}
}
我们看到这种模式,只实现了目标接口,而我们的原类通过属性的方式由构造器创建出来,最后调用原类的方法
Adapter2 a=new Adapter2(new Adaptee());
a.doSomething2();
a.doSomething1();
同样调用所有需要的方法