1.意图:
将一个类的接口转换成客户希望的另一个接口。
2.动机:
有时候,为了复用而设计的类不能够被复用的原因仅仅是因为他的接口与专业应用需要的接口不匹配。
举个例子,现在有一个汽车类,他有几个功能,比如加油、启动、制动等等,现在着汽车变得牛逼了,还能飞呢,但是我们不能在汽车基类里面加入飞的功能吧,因为这样修改了原有的基类,并且会导致不能飞的汽车(他们也继承于汽车)也有了这个功能,所以不合理。
我们想实现一个能飞的汽车类,现在有两种方法,一个是写一个派生类继承于汽车,然后给这个派生类加上一个fly()功能,还有一种方法就是,我们发现有另外一个基类,叫做flyingMachine,这个类有能飞的机器的方法fly(),我们只需要再继承或者持有这个类就行,本着复用的原则,我们采取这个办法。
其实这个就是适配器模式(adapter)。
现在讨论一下什么情况下需要用适配器:
1)想使用一个已经存在的类,但是接口不是很符合要求。
2)想创建一个可以复用的类,该类可以与其他不相关的类或者不可预见的类协同工作。
3)(这个是用于下面说的持有对象的那种Adapter)你想是用一些已经存在了的子类,但是不可能对每一个都进行子类化以匹配接口。
首先,咱们有个汽车基类,里面有些功能
public class Car {
private double fuel;
public Car(){
//create a new car;
}
public void start(){}
public void stop(){}
public void refuel(double mount){
this.fuel+=mount;
}
//.........还有一些其他功能,但是不是很想写
}
这个汽车类有三个最简单的功能(显然不是很全),启动,停止和加油。
现在咱们有一个飞行器类(我本来是写C++的,现在学了java,那么这个应该就是接口比较好)
public interface FlyMachine {
public void fly();
}
好,现在实现了一个适配器,那就是flyCar
public class FlyCar extends Car implements flyMachine{
@Override
public void fly(){
System.out.print("i am a car but a can fly");
}
}
这个FlyCar继承了Car类,并且实现了Flymachine接口,拥有了飞行技能。
这种Adapter是面向类的设计,这种设计的好处是
1)因为是继承模式,flycar类能去重新设计fly这个方法的功能。
2)相对于下面要说的面向对象的一个Adapter,这个是比较节省空间的,因为这个对象不持有接口对象的实例。
缺点其实挺明显的,就是这个flyCar'仅仅是继承了基类,却不能去使用flymathine的其他实现接口。
现在看第二种适配器的写法,采用持有对象的方式。
public class FlyCar extends Car{
private FlyCar flyCar;
public void fly(){
flyCar.fly();
}
}
这就是另一种写法,持有一个接口对象,这样优点是:
1)持有的这个对象可以指向flymathine的实现类,可以复用实现类。
但是缺点是,没法改写接口里的实现了。
从上面的例子可以看出,这个设计模式有这样几个参与者
target 就是这里的car
adaptee 定义一个已经存在的接口,这个接口需要适配。就是这里的flymathine。
adapter就是这里的flycar,这个类使两个类协同工作了。
-----------------------------------------------------------------我是分割线-----------------------------------------------------------------------
一下内容我也理解的不是很清楚,但是还是往这里记录一下。
1)适配器的匹配程度
adapter的工作量取决于adaptee和target的差别程度。
如果没什么差别,是比较简单的,如果你要实现的adapter里可能只需要实现一下接口内容,如果差别很大,需要进行一些转换。
2)可插入的adapter,为了复用,尽量别让使用的对象继承于一个很多功能的接口,这样会导致复用性降低。
3)双向适配器,就是同时继承target和adaptee,但是java不支持多重继承,如果这两个都是接口还行,不是接口好像就不行了
写完了~