经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
设计模式 | 适配器模式(adapter)
来源:cnblogs  作者:莫愆  时间:2019/6/4 15:46:39  对本文有异议

定义:

将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
 
书中说到Gof的设计模式中,讲了两种类型的适配器模式:
1.类适配器模式
2.对象适配器模式
其中,类适配器模式,是通过多重继承来实现了。
但是Java是不支持多重继承的,所以下面主要讲的是对象适配器模式。
 

结构:(书中图,侵删)

 

一个客户真正要使用的目标接口(具体一点说可以叫方法),包含它的可以是接口、抽象类、类
一个需要被适配的接口(方法),同上
一个适配器,继承自目标接口,包含一个需要被适配的接口
 

实例:

书中提到一个电源适配器的例子,很形象,所以这里提一嘴。
就是中国的电源是220V,但有的国家是110V,出国之后依旧想使用中国的电器怎么办?就需要用到适配器来转换一下电压。
说到这里,我就想到了一个例子,护照。
中国公民有中国的身份证,外国人也有外国的id card,我们不能指望外国人都用中国的身份证,同样我们也不可能都使用外国的id card。
但是出入境怎么验证你的身份呢,这就需要用到护照,护照就相当于全球通用的身份证。我们这里忽略签证的存在,签证也要盖在护照上不是。
 
目标类(外国身份认证):
  1. package designpattern.adapter;
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. public class ForeignIdentify {
  5. String socailSecurityNumber;
  6. // 模拟一个社保号的数据库
  7. static Set<String> dbSet = new HashSet<>();
  8. static {
  9. dbSet.add("F001");
  10. dbSet.add("F002");
  11. dbSet.add("F003");
  12. }
  13. public boolean check(String socailSecurityNumber) {
  14. if (dbSet.contains(socailSecurityNumber)) {
  15. System.out.println(socailSecurityNumber + "是外国的合法公民");
  16. return true;
  17. } else {
  18. System.out.println(socailSecurityNumber + "不是外国的合法公民");
  19. return false;
  20. }
  21. }
  22. }
被适配类(中国身份认证):
  1. package designpattern.adapter;
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. public class ChineseIdentify {
  5. String idCardNumber;
  6. // 模拟一个身份证号的数据库
  7. static Set<String> dbSet = new HashSet<>();
  8. static {
  9. dbSet.add("张三C001");
  10. dbSet.add("李四C002");
  11. dbSet.add("王五C003");
  12. }
  13. public boolean check(String idCardNumber, String name) {
  14. if (dbSet.contains(name + idCardNumber)) {
  15. System.out.println(name + idCardNumber + "是中国的合法公民");
  16. return true;
  17. } else {
  18. System.out.println(name + idCardNumber + "不是中国的合法公民");
  19. return false;
  20. }
  21. }
  22. }
适配器(护照):
  1. package designpattern.adapter;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. public class ChinesePassport extends ForeignIdentify {
  5. ChineseIdentify chineseIdentify = new ChineseIdentify();
  6. // 模拟身份证、名字对应数据库
  7. static Map<String, String> db = new HashMap<>();
  8. static {
  9. db.put("C001", "张三");
  10. db.put("C002", "李四");
  11. db.put("C003", "王五");
  12. }
  13. @Override
  14. public boolean check(String idCardNumber) {
  15. // 为了模拟两个接口不完全一样,假设中国的身份验证需要身份证号和名字两个条件
  16. return chineseIdentify.check(idCardNumber, getName(idCardNumber));
  17. }
  18. private String getName(String idCardNumber) {
  19. return db.get(idCardNumber);
  20. }
  21. }
客户端:
  1. package designpattern.adapter;
  2. public class Client {
  3. public static void main(String[] args) {
  4. ForeignIdentify foreignIdentify = new ForeignIdentify();
  5. enter("F001", foreignIdentify);
  6. enter("F004", foreignIdentify);
  7. // 直接用身份证号来验证
  8. enter("C003", foreignIdentify);
  9. // 换成护照
  10. foreignIdentify = new ChinesePassport();
  11. enter("C003", foreignIdentify);
  12. }
  13. public static void enter(String number, ForeignIdentify foreignIdentify) {
  14. System.out.println("=============外国入关==============");
  15. if (foreignIdentify.check(number)) {
  16. System.out.println("允许入关!");
  17. } else {
  18. System.out.println("禁止入关!");
  19. }
  20. }
  21. }

结果输出:

  1. =============外国入关==============
  2. F001是外国的合法公民
  3. 允许入关!
  4. =============外国入关==============
  5. F004不是外国的合法公民
  6. 禁止入关!
  7. =============外国入关==============
  8. C003不是外国的合法公民
  9. 禁止入关!
  10. =============外国入关==============
  11. 王五C003是中国的合法公民
  12. 允许入关!

总结:

这个模式准确的说是一个无奈的选择,不应该当做第一选择,当需要适配的两样东西不好改动的时候,为了让他们能匹配上,才不得不使用适配器。
如果能够提前避免接口不匹配的情况,及时进行代码的重构是更好的选择。就像如果说有电子设备都是同样的充电口,那我们就不需要准备他们多条充电线了。

原文链接:http://www.cnblogs.com/imoqian/p/10969743.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号