1.定义
适配器模式将一个类的接口,转换成客户期望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
2.适配器分类
(1)组合采用组合方式的适配器称为对象适配器。
特点:把“被适配者”作为一个对象组合到适配器类中,以修改目标接口包装被适配者。
(2)继承(Java是单继承)
采用继承方式的适配器称为类适配器。
特点:通过多重继承不兼容接口,实现对目标接口的匹配,单一的为某个类而实现适配
区别:
组合的方式可以适配被适配者的任何子类。由于Java是单继承的,继承的方式继承了被适配者,是为这个类单一服务的,不能再继承被适配者的任何子类。
3.组合实现
/*
* 三相插座接口
*/
public interface ThreePlugIf {
// 使用三相插座供电
public void powerWithThreePlug();
}
/*
* 二相插座接口
*/
public interface TwoPlugIf {
//使用二相插座供电
public void powerWithTwoPlug();
}
/*
* 二相插座类
*/
public class TwoPlug implements TwoPlugIf {
// 使用二相插座供电
public void powerWithTwoPlug() {
System.out.println("使用二相插座供电");
}
}
/*
* 二相转三相插座适配器
*/
public class Two2ThreeAdapter implements ThreePlugIf {
private TwoPlug plug;
public Two2ThreeAdapter(TwoPlug plug) {
this.plug = plug;
}
@Override
public void powerWithThreePlug() {
System.out.print("组合方式:");
plug.powerWithTwoPlug();
}
}
/*
* 笔记本类
*/
public class NoteBook {
private ThreePlugIf plug;
public NoteBook(ThreePlugIf plug) {
this.plug = plug;
}
// 使用插座充电
public void powerWithPlug() {
plug.powerWithThreePlug();
}
public static void main(String[] args) {
TwoPlug two = new TwoPlug();
ThreePlugIf three = new Two2ThreeAdapter(two);
NoteBook nb = new NoteBook(three);
nb.powerWithPlug();
}
}
组合方式:使用二相插座供电
4.继承实现
/*
* 三相插座接口
*/
public interface ThreePlugIf {
//使用三相插座供电
public void powerWithThreePlug();
}
/*
* 二相插座接口
*/
public interface TwoPlugIf {
//使用二相插座供电
public void powerWithTwoPlug();
}
/*
* 二相插座类
*/
public class TwoPlug implements TwoPlugIf {
// 使用二相插座供电
public void powerWithTwoPlug() {
System.out.println("使用二相插座供电");
}
}
/*
* 二相转三相插座适配器
*/
public class Two2ThreeAdapter extends TwoPlug implements ThreePlugIf {
@Override
public void powerWithThreePlug() {
System.out.print("继承方式:");
this.powerWithTwoPlug();
}
}
/*
* 笔记本类
*/
public class NoteBook {
private ThreePlugIf plug;
public NoteBook(ThreePlugIf plug) {
this.plug = plug;
}
// 使用插座充电
public void powerWithPlug() {
plug.powerWithThreePlug();
}
public static void main(String[] args) {
ThreePlugIf three = new Two2ThreeAdapter();
NoteBook nb = new NoteBook(three);
nb.powerWithPlug();
}
}
运行结果:
继承方式:使用二相插座供电
5.另一个例子:火鸡to鸭子转换器
/*
* 鸭子基类
*/
public interface Duck {
public void quack();
public void fly();
}
/*
* 绿头鸭是鸭子的子类,实现了鸭子的呱呱叫和飞行的能力
*/
public class MallardDuck implements Duck {
@Override
public void quack() {
System.out.println("Quack");
}
@Override
public void fly() {
System.out.println("I'm flying");
}
}
public interface Turkey {
// 火鸡不会呱呱叫,只会咯咯叫
public void gobble();
// 火鸡会飞,虽然飞不远
public void fly();
}
/*
* 野生火鸡
*/
public class WildTurkey implements Turkey {
@Override
public void gobble() {
System.out.println("Gobble gobble");
}
@Override
public void fly() {
System.out.println("I'm flying a short distance");
}
}
/*
* 现在,假设你缺鸭子对象,想用一些火鸡对象来冒充。
* 显而易见,因为火鸡的接口不同,所以我们不能公然拿来用。
* 那么,写个适配器吧
*/
public class Turkey2DuckAdapter implements Duck {
private Turkey turkey;
public Turkey2DuckAdapter(Turkey turkey) {
this.turkey = turkey;
}
// 现在我们需要实现接口中所有的方法。quack()在类之间的转换很简单,
// 只要调用gobble()接可以了
@Override
public void quack() {
turkey.gobble();
}
// 固然两个接口都具备了fly()方法,火鸡的飞行距离很短,不像鸭子可以长途飞行。
// 要让鸭子的飞行和火鸡的飞行能够对应,必须连续五次调用火鸡的fly()来完成
@Override
public void fly() {
for (int i = 0; i < 5; i++) {
turkey.fly();
}
}
}
/*
* 基于火鸡的鸭子
*/
public class DuckBaseTurkey {
private Duck duck;
public DuckBaseTurkey(Duck duck) {
this.duck = duck;
}
public void quack() {
duck.quack();
}
public void fly() {
duck.fly();
}
public static void main(String[] args) {
Turkey turkey = new WildTurkey();
Duck duck = new Turkey2DuckAdapter(turkey);
DuckBaseTurkey dbt = new DuckBaseTurkey(duck);
dbt.quack();
dbt.fly();
}
}