首页 > 技术文章 > 适配器模式

taoyong 2016-06-28 01:29 原文

适配器模式的定义如下:

将一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

举个栗子:设计一个用户信息管理模块。

代码清单-1  客户端访问的用户信息接口 

public interface IUserInfo {
    long getUserId();
    String getNickName();
    String getMobile();
    String getUserImgUrl();
}

代码清单-2 客户端访问的用户信息实现类

public class UserInfoImpl  implements IUserInfo{
    public long getUserId() {
        System.out.println("这里是用户的id...");
        return 0;
    }

    public String getNickName() {
        System.out.println("这里是用户的昵称...");
        return null;
    }

    public String getMobile() {
        System.out.println("这里是用户的手机号码...");
        return null;
    }

    public String getUserImgUrl() {
        System.out.println("这里是用户的头像地址...");
        return null;
    }
}

正常情况下,UserInfoImpl几个get方法可以通过查询数据库拿到数据。可是有时候用户信息是通过远程调用服务获取的,其返回的用户信息对象和我们以上的接口不一致。

代码清单-3 远程调用发布的用户信息接口

public interface IUserInfoExport {
    
    /**
     * 用户基本信息:id,昵称,手机号,用户头像地址
     * @return 用户信息Map
     */
    Map getUserBaseInfo();

}

代码清单-4 对应对实现类

public class UserInfoExportImpl implements IUserInfoExport {
    public Map getUserBaseInfo() {
        Map map = new HashMap();
        map.put("userId","这里是用户的id...");
        map.put("nickName","这里是用户的昵称...");
        map.put("mobile","这里是用户的手机号码...");
        map.put("userImgUrl","这里是用户的头像地址...");
        return map;
    }
}

这时,我们为了不改动原系统代码的情况下,新增一个"适配器",通过它使远程调用获得的用户信息转化成客户端访问的用户信息

代码清单-5 适配器实现

public class UserInfoAdapter extends UserInfoExportImpl implements IUserInfo{
    Map userInfoMap = super.getUserBaseInfo();
    public long getUserId() {
        long userId = (Long)userInfoMap.get("userId");
        return userId;
    }

    public String getNickName() {
        String nickName = (String)userInfoMap.get("nickName");
        return nickName;
    }

    public String getMobile() {
        String mobile = (String)userInfoMap.get("moblie");
        return mobile;
    }

    public String getUserImgUrl() {
        String userImgUrl = (String)userInfoMap.get("userImgUrl");
        return userImgUrl;
    }
}

如果用户信息不仅仅来自IUserInfoExport一个接口,例如还有提供用户额外信息接口等IUserExtInfoExport,适配器UserInfoAdapter就同时继承两个Export实现类了.

这时候可以用另一种适配器实现方法.

代码清单-6

public class UserInfoAdapter implements IUserInfo{
    IUserInfoExport userInfoExport = null;
    Map userInfoMap = null;
    
    public UserInfoAdapter(IUserInfoExport userInfoExport){
        this.userInfoExport = userInfoExport;
        this.userInfoMap = this.userInfoExport.getUserBaseInfo();
    }
    
    public long getUserId() {
        long userId = (Long)userInfoMap.get("userId");
        return userId;
    }

    public String getNickName() {
        String nickName = (String)userInfoMap.get("nickName");
        return nickName;
    }

    public String getMobile() {
        String mobile = (String)userInfoMap.get("moblie");
        return mobile;
    }

    public String getUserImgUrl() {
        String userImgUrl = (String)userInfoMap.get("userImgUrl");
        return userImgUrl;
    }
}

代码清单-5是类适配器模式,代码清单-6是对象适配器模式。两者本质的区别是:类适配器是类之间的继承,对象适配器是对象的合成关系,也可以说是类的关联关系。一般对象适配器模式实际场景使用较多。

代码清单-7  类适配器的场景类

public class Client {
    public static void main(String[] args){
        IUserInfo userInfo = new UserInfoAdapter();
        userInfo.getUserId();
        userInfo.getMobile();
        userInfo.getNickName();
        userInfo.getUserImgUrl();
    }
}

代码清单-8 对象适配器的场景类

public class Client {
    public static void main(String[] args){
        IUserInfoExport userInfoExport = new UserInfoExportImpl();
        IUserInfo userInfo = new UserInfoAdapter(userInfoExport);
        userInfo.getUserId();
        userInfo.getMobile();
        userInfo.getNickName();
        userInfo.getUserImgUrl();
    }
}

 

推荐阅读