适配器模式是什么
适配器模式将一个接口转换成客户希望的另外一个接口。它使得原来由于接口不兼容而不能在一起工作的那些类可以一起工作。是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
适配器能什么
有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。适配器不是在详细设计时添加的,而是解决正在服役的项目的问题。其实适配器模式有点无奈之举,在前期设计的时候,我们就不应该考虑适配器模式,而应该考虑通过重构统一接口。
适配器模式优缺点
优点:
1、可以让任何两个没有关联的类一起运行。
2、可以将现有接口转化为客户需要的接口,提高了类的复用。
3、具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用。
4、灵活性好,可以在不修改原代码情况下进行适配,符合开闭原则。
缺点:
1、过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
2、由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类。单继承的局限性。
辅助图示
如上图所示
将两个无关联的类组合起来,除此之外提供新功能,提供给客户希望的另外一个接口。 原接口只有篮球和足球运动,新适配的接口即有篮球和足球,更有新功能提供给客户使用。
示例代码
1、原有接口和实现类
public interface UserPlayer { void doPlayBasketBallAction(String userName); void doPlayFootBallAction(String userName); }
public class BaskBallPlayer implements UserPlayer{ @Override public void doPlayBasketBallAction(String userName) { System.out.println(userName + " can do play basketball。"); } @Override public void doPlayFootBallAction(String userName) { //do nothing } }
public class FootBallPlayer implements UserPlayer{ @Override public void doPlayBasketBallAction(String userName) { //do nothing } @Override public void doPlayFootBallAction(String userName) { System.out.println(userName + " can do play football。"); } }
2、适配接口和实现类
public interface PlayerDoPlay { void doPlay(String action, String userName); }
public class AdvancedPlayer implements PlayerDoPlay { private PlayerDoPlayAdapter doPlayAdapter; @Override public void doPlay(String action, String userName) { //高级玩家扩展功能 if (action.equalsIgnoreCase("play pingpang") && userName.equals("Player3")){ System.out.println(userName + " can play pingpang。"); }else if (action.equalsIgnoreCase("play basketball") || action.equalsIgnoreCase("play football") || userName.equals("Player3")){ doPlayAdapter = new PlayerDoPlayAdapter(action); doPlayAdapter.doPlay(action, userName); }else { System.out.println(userName + " can not do this action!"); } } }
/** * Adapter */ public class PlayerDoPlayAdapter implements PlayerDoPlay { private UserPlayer userPlayer; public PlayerDoPlayAdapter(String action){ if(action.equalsIgnoreCase("play basketball") ){ userPlayer = new BaskBallPlayer(); } else if (action.equalsIgnoreCase("play football")){ userPlayer = new FootBallPlayer(); } } @Override public void doPlay(String action, String userName) { if(action.equalsIgnoreCase("play basketball")){ userPlayer.doPlayBasketBallAction(userName); }else if(action.equalsIgnoreCase("play football")){ userPlayer.doPlayFootBallAction(userName); } } }
3、客户端
public class TestPlayer { public static void main(String[] args) { AdvancedPlayer advancedPlayer = new AdvancedPlayer(); //Player1 can play basketball //Player2 can play football //Player3 can play pingpang and football and basketball advancedPlayer.doPlay("play pingpang", "Player3"); advancedPlayer.doPlay("play basketball", "Player3"); advancedPlayer.doPlay("play football", "Player3"); advancedPlayer.doPlay("play pingpang", "Player2"); advancedPlayer.doPlay("play basketball", "Player1"); advancedPlayer.doPlay("play football", "Player2"); } }
运行结果
Player3 can play pingpang。 Player3 can do play basketball。 Player3 can do play football。 Player2 can not do this action! Player1 can do play basketball。 Player2 can do play football。