适配器模式

111 阅读6分钟
一,适配器模式的定义

      适配器模式定义如下:

      将一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够一起工作。适配器模式又叫变压器模式,也叫作包装模式。

      A,B两个图框已经塑模成型的物体A和物体B,那现在要求把A和B安装在一起使用,如何安装?两者的接口不一致,是不能安装在一起使用的,那怎么办?引入一个物体C,如图19-6所示。

image.png

      引入物体C后,C适应了物体A的接口,同时也适应了物体B的接口,然后三者就可以组合成一个完整的物体,如图19-7所示。

image.png

      其中的物体C就是我们说的适配器,它在中间起到了角色转换的作用,把原有的长条形接口转换了三角形接口。在我们软件业的设计模式中,适配器模式也是相似的功能,那我们先看看适配器模式的三个角色。

  1. Target目标角色

          该角色定义把其他类转化为何种接口,也就是我们的期待接口。代码如下:

    package cn.edu.njtech.book.adapter;
    
    public interface Target {
        // 目标角色自己的方法
        public void request();
    }
    
    
    package cn.edu.njtech.book.adapter;
    
    public class ConcreteTarget implements Target {
        @Override
        public void request() {
            System.out.println("if you need any help,pls call me!");
        }
    }
    
  2. Adaptee源角色

          你想把谁转换成目标角色,这个"谁"就是源角色,它是已经存在的,运行良好的类或对象,经过适配器角色的包装,它会变成一个崭新的,靓丽的角色。代码如下:

    package cn.edu.njtech.book.adapter;
    
    public class Adaptee {
        // 原有的业务逻辑
        public void doSomething() {
            System.out.println("I'am kind of busy,leave me alone,pls!");
        }
    }
    
  3. Adapter适配器角色

          适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:把源角色转化为目标角色,怎么转换?通过继承或是类关联的方式。

    package cn.edu.njtech.book.adapter;
    
    public class Adapter extends Adaptee implements Target {
        @Override
        public void request() {
            super.doSomething();
        }
    }
    
  4. 所有的角色都已经在场了,那我们就开始看看这场演出,场景类代码如下:

    package cn.edu.njtech.book.adapter;
    
    public class ClientTwo {
        public static void main(String[] args) {
            // 原有的业务逻辑
            Target target = new ConcreteTarget();
            target.request();
            // 现在增加了适配器角色后的业务逻辑
            Target target1 = new Adapter();
            target1.request();
        }
    }
    
二,通过继承实现适配

      假如我们公司原始的员工信息功能完备,这个时候从外面公司借一部分员工过来,别的公司的员工信息接口和我们公司的接口互不兼容,这个时候,适配器的角色可以上战场了。

  1. IUserInfo

    package cn.edu.njtech.book.adapter;
    
    public interface IUserInfo {
        public String getUserName();
    
        public String getHomeAddress();
    
        public String getMobileNumber();
    
        public String getOfficeTelNumber();
    
        public String getJobPosition();
    
        public String getHomeTelNumber();
    }
    
  2. UserInfo

    package cn.edu.njtech.book.adapter;
    
    public class UserInfo implements IUserInfo {
        @Override
        public String getUserName() {
            System.out.println("姓名叫做...");
            return null;
        }
    
        @Override
        public String getHomeAddress() {
            System.out.println("这里是员工的家庭住址...");
            return null;
        }
    
        @Override
        public String getMobileNumber() {
            System.out.println("这个人的手机号是0000...");
            return null;
        }
    
        @Override
        public String getOfficeTelNumber() {
            System.out.println("办公室电话是...");
            return null;
        }
    
        @Override
        public String getJobPosition() {
            System.out.println("这个人的职位是BOSS...");
            return null;
        }
    
        @Override
        public String getHomeTelNumber() {
            System.out.println("员工的家庭电话是...");
            return null;
        }
    }
    
  3. IOuterInfo

    package cn.edu.njtech.book.adapter;
    
    import java.util.Map;
    
    public interface IOuterUser {
        public Map getUserBaseInfo();
    
        public Map getUserOfficeInfo();
    
        public Map getUserHomeInfo();
    }
    
    
  4. OuterUser

    package cn.edu.njtech.book.adapter;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class OuterUser implements IOuterUser {
        @Override
        public Map getUserBaseInfo() {
            HashMap baseInfoMap = new HashMap();
            baseInfoMap.put("userName", "这个员工叫混世魔王...");
            baseInfoMap.put("mobileNumber", "这个员工电话是...");
            return baseInfoMap;
        }
    
        @Override
        public Map getUserOfficeInfo() {
            HashMap officeInfo = new HashMap();
            officeInfo.put("jobPosition", "这个人的职位是BOSS...");
            officeInfo.put("officeTelNumber", "员工的办公电话是...");
            return officeInfo;
    
        }
    
        @Override
        public Map getUserHomeInfo() {
            HashMap homeInfo = new HashMap();
            homeInfo.put("homeTelNumber", "员工的家庭电话是...");
            homeInfo.put("homeAddress", "员工的家庭住址是...");
            return homeInfo;
        }
    }
    
    
  5. 适配器类

    package cn.edu.njtech.book.adapter;
    
    import java.util.Map;
    
    public class OuterUserInfoOne extends OuterUser implements IUserInfo {
        private Map baseInfo = super.getUserBaseInfo();
        private Map homeInfo = super.getUserHomeInfo();
        private Map officeInfo = super.getUserOfficeInfo();
    
        @Override
        public String getUserName() {
            String userName = (String) this.baseInfo.get("userName");
            System.out.println(userName);
            return userName;
        }
    
        @Override
        public String getHomeAddress() {
            String homeAddress = (String) this.homeInfo.get("homeAddress");
            System.out.println(homeAddress);
            return homeAddress;
        }
    
        @Override
        public String getMobileNumber() {
            String mobileNumber = (String) this.baseInfo.get("mobileNumber");
            System.out.println(mobileNumber);
            return mobileNumber;
        }
    
        @Override
        public String getOfficeTelNumber() {
            String officeTelNumber = (String) this.officeInfo.get("officeTelNumber");
            System.out.println(officeTelNumber);
            return officeTelNumber;
        }
    
        @Override
        public String getJobPosition() {
            String jobPosition = (String) this.officeInfo.get("jobPosition");
            System.out.println(jobPosition);
            return jobPosition;
        }
    
        @Override
        public String getHomeTelNumber() {
            String homeTelNumber = (String) this.homeInfo.get("homeTelNumber");
            System.out.println(homeTelNumber);
            return homeTelNumber;
        }
    }
    
    
  6. 场景类

    package cn.edu.njtech.book.adapter;
    
    public class ClientOne {
        public static void main(String[] args) {
            IUserInfo youngGirl = new UserInfo();
            for (int i = 0; i < 101; i++) {
                youngGirl.getMobileNumber();
            }
            IUserInfo youngGirlOuter = new OuterUserInfoOne();
            for (int i = 0; i < 101; i++) {
                youngGirlOuter.getMobileNumber();
            }
        }
    }
    
三,类关联方式实现适配

      Java是单继承的,如果我们的源角色分了三个类,每个类分别实现了三个接口。可以使用类关联的方法,声明一个OuterUserInfo实现类,实现了IUserInfo接口,通过再关联其他三个类就可以解决这个问题了。

  1. 用户基本信息接口

    package cn.edu.njtech.book.adapter;
    
    import java.util.Map;
    
    public interface IOuterUserBaseInfo {
        public Map getUserBaseInfo();
    }
    
    
  2. 用户家庭信息接口

    package cn.edu.njtech.book.adapter;
    
    import java.util.Map;
    
    public interface IOuterUserHomeInfo {
        public Map getUserHomeInfo();
    }
    
    
  3. 用户工作信息接口

    package cn.edu.njtech.book.adapter;
    
    import java.util.Map;
    
    public interface IOuterUserOfficeInfo {
        public Map getUserOfficeInfo();
    }
    
    
  4. 用户基本信息

    package cn.edu.njtech.book.adapter;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class OuterUserBaseInfo implements IOuterUserBaseInfo {
        @Override
        public Map getUserBaseInfo() {
            HashMap baseInfoMap = new HashMap();
            baseInfoMap.put("userName", "这个员工叫混世魔王...");
            baseInfoMap.put("mobileNumber", "这个员工电话是...");
            return baseInfoMap;
        }
    }
    
    
  5. 用户家庭信息

    package cn.edu.njtech.book.adapter;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class OuterUserHomeInfo implements IOuterUserHomeInfo {
        @Override
        public Map getUserHomeInfo() {
            HashMap homeInfo = new HashMap();
            homeInfo.put("homeTelNumber", "员工的家庭电话是...");
            homeInfo.put("homeAddress", "员工的家庭住址是...");
            return homeInfo;
        }
    }
    
    
  6. 用户工作信息

    package cn.edu.njtech.book.adapter;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class OuterUserOfficeInfo implements IOuterUserOfficeInfo {
        @Override
        public Map getUserOfficeInfo() {
            HashMap officeInfo = new HashMap();
            officeInfo.put("jobPosition", "这个人的职位是BOSS...");
            officeInfo.put("officeTelNumber", "员工的办公电话是...");
            return officeInfo;
        }
    }
    
    
  7. 适配器

    package cn.edu.njtech.book.adapter;
    
    import java.util.Map;
    
    public class OuterUserInfoTwo implements IUserInfo {
        private IOuterUserBaseInfo baseInfo = null;
        private IOuterUserHomeInfo homeInfo = null;
        private IOuterUserOfficeInfo officeInfo = null;
    
        private Map baseMap = null;
        private Map homeMap = null;
        private Map officeMap = null;
    
        public OuterUserInfoTwo(IOuterUserBaseInfo baseInfo, IOuterUserHomeInfo homeInfo, IOuterUserOfficeInfo officeInfo) {
            this.baseInfo = baseInfo;
            this.homeInfo = homeInfo;
            this.officeInfo = officeInfo;
    
            this.baseMap = this.baseInfo.getUserBaseInfo();
            this.homeMap = this.homeInfo.getUserHomeInfo();
            this.officeMap = this.officeInfo.getUserOfficeInfo();
        }
    
        @Override
        public String getUserName() {
            String userName = (String) this.baseMap.get("userName");
            System.out.println(userName);
            return userName;
        }
    
        @Override
        public String getHomeAddress() {
            String homeAddress = (String) this.homeMap.get("homeAddress");
            System.out.println(homeAddress);
            return homeAddress;
        }
    
        @Override
        public String getMobileNumber() {
            String mobileNumber = (String) this.baseMap.get("mobileNumber");
            System.out.println(mobileNumber);
            return mobileNumber;
        }
    
        @Override
        public String getOfficeTelNumber() {
            String officeTelNumber = (String) this.officeMap.get("officeTelNumber");
            System.out.println(officeTelNumber);
            return officeTelNumber;
        }
    
        @Override
        public String getJobPosition() {
            String jobPosition = (String) this.officeMap.get("jobPosition");
            System.out.println(jobPosition);
            return jobPosition;
        }
    
        @Override
        public String getHomeTelNumber() {
            String homeTelNumber = (String) this.homeMap.get("homeTelNumber");
            System.out.println(homeTelNumber);
            return homeTelNumber;
        }
    }
    
    
  8. 场景类

    package cn.edu.njtech.book.adapter;
    
    public class ClientThree {
        public static void main(String[] args) {
            IOuterUserBaseInfo baseInfo = new OuterUserBaseInfo();
            IOuterUserHomeInfo homeInfo = new OuterUserHomeInfo();
            IOuterUserOfficeInfo officeInfo = new OuterUserOfficeInfo();
    
            IUserInfo youngGirl = new OuterUserInfoTwo(baseInfo, homeInfo, officeInfo);
            for (int i = 0; i < 101; i++) {
                youngGirl.getMobileNumber();
            }
        }
    }
    
    
四,适配器模式的优点
  1. 适配器可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定他们就成。
  2. 增加了类的透明性。
  3. 提高了类的复用度
  4. 灵活性非常好。
五,写在最后

      适配器模式最好在详细设计阶段不要考虑它,它不是为了解决还处在开发阶段的问题,而是解决正在服役的项目问题,没有一个系统分析师会在做详细设计的时候考虑使用适配器模式,这个模式使用的主要场景是扩展应用中。