如何通关设计模式之适配器模式

“补救模式”

经常在业务开发过程中都会遇到需求变动等情况,一个再好的程序猿也难免设计出一个“完美”的业务系统。因为,需求永远是变化的。

“智者千虑必有一失,愚者千虑必有一得”,我们都是平庸之人,无法做到百分百的完美系统,对于有些“意外”,该来的总会来,而为了去弥补这些意外,就需要使用到一些补救措施。这个补救措施叫做适配器模式,也可以说是一种补救模式。

适配器的“补救”

假如我是一个公司的老大,今天突然想查看下公司人员信息的情况,但是呀这个公司的人员分布比较复杂,主要分为两种,一种是公司在职人员,另一种是公司外包人员,公司在职人员属于本公司正式的人员,而外包人员是聘请的外部公司的人员。我想要看看公司这些人员的情况,于是叫来程序猿小张,让他帮我把公司人员信息统计出来。

程序猿小张接到这个任务,做了简单的分析,公司在职人员的信息都存储在公司自身的数据库中很好调用,但是那些外包人员的信息存储在他们公司的数据库中,面对这种情况小张有点懵了,因为两个公司查找人员信息的方法不同,那么该怎么下手了。还好,对于外包人员公司提供了可以调取外包人信息的接口,既然接口有了,那就开始干活吧。

先来看看本公司对于人员信息调用的接口以及实现:

//本公司人员查询接口
public interface AbstractUserInfo {

    String getUserName();

    String getHomeAddress();

    String getMobileNumber();

    String getUserAge();

}

public class UserInfo implements AbstractUserInfo {
    @Override
    public String getUserName() {
        return "隔壁老王";
    }

    @Override
    public String getHomeAddress() {
        return "天庭128号";
    }

    @Override
    public String getMobileNumber() {
        return "10086";
    }

    @Override
    public String getUserAge() {
        return "3210岁";
    }
}

本公司查询在职人员信息的接口十分简单,再来看看外包公司对于人员信息查询接口:

//外包公司人员查询接口
public interface AbstractOuterUserInfo {

    Map getUserBaseInfo();

    Map getUserHomeInfo();

}

public class OuterUserInfo implements AbstractOuterUserInfo {

    @Override
    public Map<String, String> getUserBaseInfo() {
        HashMap<String, String> map = new HashMap<>();
        map.put("userName", "外包1号");
        map.put("phone", "100001");
        map.put("age", "60");
        return map;
    }

    @Override
    public Map<String, String> getUserHomeInfo() {
        HashMap<String, String> map = new HashMap<>();
        map.put("address", "黄河边");
        return map;
    }
}

该公司对于人员查询接口的设计十分古怪,不说该接口设计的正确与否,可是如何才能实现对两边公司人员信息查询的同时调用呢,难道需要将本公司的接口代码重构修改成外包公司那样的接口?当然不,先不说这会不会引起程序猿们的公愤,这也不是一个公司老大想看到的,万一以后还有外包公司A,外包公司B…

这个时候适配器模式就登场了,它能够很好的兼容两个不相关的类,来达到相同的效果。先来看看这个模式的庐山真面目吧。

public class AdapterUserInfo extends OuterUserInfo implements AbstractUserInfo{
    @Override
    public String getUserName() {
        return this.getUserBaseInfo().get("userName");
    }

    @Override
    public String getHomeAddress() {
        return this.getUserHomeInfo().get("address");
    }

    @Override
    public String getMobileNumber() {
        return this.getUserBaseInfo().get("phone");
    }

    @Override
    public String getUserAge() {
        return this.getUserBaseInfo().get("age");
    }
}

通过创建AdapterUserInfo类,让它继承OuterUserInfo并实现AbstractUserInfo,在实现方法中重写其中的方法,获得继承的父类中的值,便可轻松实现两个不相关类在一起运行。

现在只需要通过创建AdapterUserInfoUserInfo对象,即可进行员工信息查询,并且查询的方法名以及参数都是相同的,这样就可以很方便的进行不同接口下的员工信息查询了。该方法不仅简单,而且有着极强的扩展性,当我们不需要该外包公司的接口时,直接删除对应类即可,不需要修改系统自身的代码。而且,当有外包公司A、外包公司B时,我们也仅仅再继承其提供的接口就可以了。

这种适配器模式也可以叫类适配器,它主要是通过继承一个类来是实现的。

适配器的应用

优点:
  1. 适配器模式可以让两个没有任何关系的类在一起运行。
  2. 增加了类的透明性。
  3. 提高了类的复用性。
  4. 灵活性非常好。
扩展

在上述的栗子中,我们通过继承外包公司提供的OuterUserInfo接口,便完成了对该公司人员信息的查询。可是万一,该公司提供的接口不止一个会是种什么情况呢。

//外包公司人员基础信息查询接口
public interface AbstractOuterUserBaseInfo {
    Map<String, String> getUserBaseInfo();
}
//外包公司人员家庭信息查询接口
public interface AbstractOuterUserHomeInfo {
    Map<String, String> getUserHomeInfo();
}

//基础信息接口实现
public class OuterUserBaseInfo implements AbstractOuterUserBaseInfo {

    @Override
    public Map<String, String> getUserBaseInfo() {
        HashMap<String, String> map = new HashMap<>();
        map.put("userName", "大哥");
        map.put("phone", "19940790216");
        map.put("age", "16");
        return map;
    }
}
//家庭信息接口实现
public class OuterUserHomeInfo implements AbstractOuterUserHomeInfo {
    @Override
    public Map<String, String> getUserHomeInfo() {
        HashMap<String, String> map = new HashMap<>();
        map.put("address", "四川");
        return map;
    }
}

看到这,如果再使用我们上述的类适配器显然是不太合适的,我们都知道java只支持单继承,而无法使一个类继承于多个类,这个时候该怎么办了呢,其实很简单,请往下看。

public class AdapterUserInfo implements AbstractUserInfo {

    AbstractOuterUserBaseInfo outerUserBaseInfo;
    AbstractOuterUserHomeInfo outerUserHomeInfo;

    public AdapterUserInfo(AbstractOuterUserBaseInfo outerUserBaseInfo,
						AbstractOuterUserHomeInfo outerUserHomeInfo) {
        this.outerUserBaseInfo = outerUserBaseInfo;
        this.outerUserHomeInfo = outerUserHomeInfo;
    }

    @Override
    public String getUserName() {
        return outerUserBaseInfo.getUserBaseInfo().get("userName");
    }

    @Override
    public String getHomeAddress() {
        return outerUserHomeInfo.getUserHomeInfo().get("address");
    }

    @Override
    public String getMobileNumber() {
        return outerUserBaseInfo.getUserBaseInfo().get("phone");
    }

    @Override
    public String getUserAge() {
        return outerUserBaseInfo.getUserBaseInfo().get("age");
    }
}

这段代码只需要关注该类的构造器处即可,通过构造器初始化outerUserBaseInfoouterUserHomeInfo对象,再通过实现AbstractUserInfo类中的方法调用两个对象中的数据就能很方便的适应需要继承多个类的情况。这种适配器模式叫做对象适配器。

总结

适配器模式是一种补救模式,通常用来解决接口不兼容的问题。没有百分之百完美的设计,再完美的设计也会遇到需求变动的问题,这也是我们无法逃避的一个事实,在业务日新月异的同时,对于技术的提升也带来了巨大的挑战,在关键时刻,适配器模式也会给我们带来不一般的便利。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值