当现有的某个类的接口不能满足客户所需要的接口,需要将这个类的接口转换为客户想要的接口,可以使用适配器模式。这相当于给接口做了一个适配,使这个接口可以在现有的模块内可以使用。
举一个简单的例子,我们国家家用电网提供的是220V交流电,对于台式机而言,主板需要12V直流电,当然不能直接拿交流电来使用啦。所以主机都有一个电源适配器,将220V 交流电 转换成 12V直流电。这个电源适配器就是从中间起到了一个转换的作用。
看一下类图:
package com.lou.adapter.instance; public interface AbstractComputerPower { /* * 直流电电源 提供直流电 */ public String provideDirectCurrent(); }
package com.lou.adapter.instance; public interface AbstractNationalPower { /* * 国家电网提供交流电 */ public String provideAlternatableCurrent(); }
package com.lou.adapter.instance; public class ComputerPowerAdapter implements AbstractComputerPower { private AbstractNationalPower power = new ChinesePower(); @Override public String provideDirectCurrent() { String nationalPower = power.provideAlternatableCurrent(); return transfer(nationalPower); } private String transfer(String nationalPower) { System.out.println( "对交流电整流,变压,输出直流电"); return "12V 直流电"; } }
package com.lou.adapter.instance; public class Client { public static void main(String[] args) { AbstractComputerPower computerPower = new ComputerPowerAdapter(); computerPower.provideDirectCurrent(); } }
package com.lou.adapter.instance; public class ChinesePower implements AbstractNationalPower { @Override public String provideAlternatableCurrent() { return "220V 交流电。"; } }
综上,适配器模式是指:
适配器的通用模型为:
适配器模式最后真正完成业务的还是靠原来的接口,adapter从中间起到了转换,代理的作用。
再举一个更实际的例子:
在 项目中会涉及到查询用户信息的相关操作,在当前系统内,既有的底层提供的用户信息接口如下:
package com.lou.patterns.adapter; public interface UserInfo { public String getUserName(); public String getUserId(); public Integer getUserAge(); public String getUserProvince(); public String getUserCity(); public String getUserStreet(); }
当前系统内,用户查询接口 可以查询 用户名,用户id,年龄 ,用户所在的省份,所在的城市,所在的街道。
但是现在系统的另外一个模块定义的用户查询 接口如下:
package com.lou.patterns.adapter; public interface UserInformation { public String getUserName(); public String getUserId(); public Integer getUserAge(); //UserAddredss = province + city + street; public String getUserAddress(); }
即:这个模块定义的用户查询接口应该为 查询用户名,用户id,用户年龄,用户的地址
现在就会存在问题:因为这个模块定义的接口和底层定义的接口不兼容,无法将底层的UserInfo 实现类直接拿来使用,现在要在这两个接口之间架起一道桥梁,使我们可以是两个模块兼容起来,所以,我们构造一个适配器,这个适配器要能完成 UserInformation 定义的功能:
package com.lou.patterns.adapter; public class UserInfoAdapter implements UserInformation{ private UserInfo userInfo; @Override public String getUserName() { return userInfo.getUserName(); } @Override public String getUserId() { return userInfo.getUserId(); } @Override public Integer getUserAge() { return userInfo.getUserAge(); } @Override public String getUserAddress() { return userInfo.getUserProvince()+" " + userInfo.getUserCity()+ " " +userInfo.getUserStreet(); } }
package com.lou.patterns.adapter; public class UserInfoImpl implements UserInfo{ UserBean userBean = new UserBean(); @Override public String getUserName() { return userBean.getName(); } @Override public String getUserId() { return userBean.getId(); } @Override public Integer getUserAge() { return userBean.getAge(); } @Override public String getUserProvince() { return userBean.getProvince(); } @Override public String getUserCity() { return userBean.getCity(); } @Override public String getUserStreet() { return userBean.getStreet(); } }
package com.lou.patterns.adapter; public class UserBean { private String name; private String id; private Integer age; private String province; private String city; private String street; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } }
这样,两个模块就可以兼容起来使用了。
总结:
适配器模式在于,adaptee在系统中的不可代替性,一般为模块的底层或者是基础部分,当遇到不兼容的情况时,不方便或者对于当前系统稳定性和拓展性的考虑,应当遵循 “对修改关闭,对拓展开放”的原则,使用适配器模式可以很好地满足这一点。
这里的适配器模式,有一定程度的代理模式的意味在里面,真正业务的实现偏重在adaptee实现,adapter再对其进行转换,满足另外一个模块的要求。
个人观点,欢迎拍砖。