很多时候我们需要解决遗留代码的问题,例如遗留代码暴露出的接口方法需要的参数列表跟调用者提供的参数列表不一致,那么如何解决这种冲突呢,在解决这种问题的时候,我第一时间想到的解决方案就是使用适配器模式。
适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
考虑这样一个场景,我们有一个遗留系统提供一个greeting的接口,但是由于某种客观原因(例如客户能提供的参数跟遗留系统需求的参数不一致或客户无法直接访问遗留系统),客户端只能访问新系统的sayHello方法,本质上这两个方法做的事情是一样的,这个时候我们可以编写一个适配器类来解决这种尴尬的问题,先上UML类图来描述一下类之间的协作关系。
再来看看代码,其实有时候看代码更直接。
遗留系统暴露的接口:
package com.singland.dp.adapter2; public interface LegacySystem { public void greeting(String username); }
遗留系统接口的具体实现类:
package com.singland.dp.adapter2; public class LegacySystemImpl implements LegacySystem { @Override public void greeting(String username) { System.out.println(String.format("Hello %s, greetings from Legacy System greeting method !", username)); } }
新系统的接口:
package com.singland.dp.adapter2; public interface NewSystem { public void sayHello(String username); }
新系统的具体实现类:
package com.singland.dp.adapter2; public class NewSystemImpl implements NewSystem { @Override public void sayHello(String username) { System.out.println(String.format("Hello %s, greetings from New System !", username)); } }
重头戏在这里,适配器类:
package com.singland.dp.adapter2; public class LegacySystemAdapter implements NewSystem { private LegacySystem legacySystem; public LegacySystemAdapter(LegacySystem legacySystem) { this.legacySystem = legacySystem; } @Override public void sayHello(String username) { legacySystem.greeting(username); } }
我的测试类:
package com.singland.dp.adapter2; import org.junit.Test; public class MyTest { @Test public void test() { LegacySystem legacySystem = new LegacySystemImpl(); NewSystem adapter = new LegacySystemAdapter(legacySystem); adapter.sayHello("Stone"); } }
运行结果:
适配器模式让我们可以重用遗留代码,在例子中客户端甚至不知道真正调用的是遗留系统的代码,真正做到了新瓶装老酒,换汤不换药的功效啊:)