适配器(Adapter)大家应该都不会陌生,比如电源适配器。比如我的手机电源适配器,一边插双孔插头,一边可以插USB,这其实就是现实世界的适配器模式(Adapter DP)。说白了很简单,就是适配接口。
适配器有两种,类适配器和对象适配器。类适配器是通过继承被适配者的接口,对象适配器则是通过组合来获得被适配者的接口。由于Java不支持多个继承,一般使用对象适配器不占用继承,不过也不是说类适配器就不能用。
代码:
战舰接口:
/**
* The interface expected by the client.<br>
* A Battleship can fire and move.
*
*/
public interface BattleShip {
void fire();
void move();
}
船长,驾驶战舰运动和开火:
/**
* The Captain uses {@link BattleShip} to fight. <br>
* This is the client in the pattern.
*/
public class Captain implements BattleShip {
private BattleShip battleship;
public Captain() {
}
public Captain(BattleShip battleship) {
this.battleship = battleship;
}
public void setBattleship(BattleShip battleship) {
this.battleship = battleship;
}
@Override
public void fire() {
battleship.fire();
}
@Override
public void move() {
battleship.move();
}
}
被适配者,渔船:
/**
*
* Device class (adaptee in the pattern). We want to reuse this class
*
*/
public class FishingBoat {
private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoat.class);
public void sail() {
LOGGER.info("The Boat is moving to that place");
}
public void fish() {
LOGGER.info("fishing ...");
}
}
这里渔船是一个类而不是接口,不过渔船可以看成使用渔船接口的一个类,影响不大。
现在我们要做的就是把渔船适配给船长当做战舰。
那么需要一个适配器:
/**
*
* Adapter class. Adapts the interface of the device ({@link FishingBoat}) into {@link BattleShip}
* interface expected by the client ({@link Captain}). <br>
* In this case we added a new function fire to suit the interface. We are reusing the
* {@link FishingBoat} without changing itself. The Adapter class can just map the functions of the
* Adaptee or add, delete features of the Adaptee.
*
*/
public class BattleFishingBoat implements BattleShip {
private static final Logger LOGGER = LoggerFactory.getLogger(BattleFishingBoat.class);
private FishingBoat boat;
public BattleFishingBoat() {
boat = new FishingBoat();
}
@Override
public void fire() {
LOGGER.info("fire!");
}
@Override
public void move() {
boat.sail();
}
}
这个适配器值得认真研究。这是一个对象适配器,采用了战舰接口,同时通过组合,有一个渔船类,适配器就可以用渔船的方法来实现战舰的方法。
因为是组合,所以渔船必须使用一个实例。假如之前改成渔船接口,这里照样需要在一个地方传入渔船接口的实现类,这样才能调用渔船的方法。
假如是类适配器,就直接继承渔船并实现战舰接口,因为自己已经是渔船了,可以直接用自己的方法来实现战舰方法,就不再赘述了。