Java设计模式之适配器模式

适配器模式,其一般应用场合为系统打补丁。可以用以下这个例子说明:你家的自来水系统(原系统)水管直径都是5cm,原来你家的洗衣机进水口也是5cm,刚好可以将家里的水管接入到洗衣机里,这样用着挺好。可突然有一天,你家原来的洗衣机坏了,市面上能买到的洗衣机进水口都是3cm(新业务)的,这怎么办呢?一般情况下,我们不会把家里运行良好的自来水系统管道来个大改造来适应你这个新洗衣机,而是买个转接器(适配器),一头直径5cm接自来水,一头3cm接新洗衣机,就能使规格不一样的新洗衣机可以接入到原来的自来水系统了。而这里用括号标明的原有系统,新业务以及适配器的概念,就可以泛化引申到我们的系统设计中来了。所谓适配器模式,就是一种“补救”模式,用来解决接口不相容的问题。那么怎么做呢?下面用一个简单实例来说明。
首先,假设我们的原系统是一个交易报表系统,公司原业务都是在国内发生的,所以交易报表都是基于国内交易设计的。
我们第一步定义一个基于人民币的交易接口(IRMBDeal),只做示意,这里获取交易省份、城市以及人民币金额。

/**
 * Created by Song on 2017/1/18.
 * 一宗人民币交易
 */
public interface IRMBDeal {
    //获取交易省份
    String getProvince();
    //获取交易城市
    String getCity();
    //获取交易金额(人民币)
    int getRMB();
}

在我们的交易报表业务类中,我们是这样打印我们的交易信息的:

/**
 * Created by Song on 2017/1/18.
 * 交易报表
 */
public class TradingStatement {
    public void report(IRMBDeal deal){
        System.out.println("交易省份:"+deal.getProvince());
        System.out.println("交易城市:"+deal.getCity());
        System.out.println("交易金额(RMB):"+deal.getRMB());
    }
}

再具体调用中,我们可以实现IRMBDeal接口,并传入TradingStatement 实例的report方法就可以打印交易消息了。例如:


/**
 * Created by Song on 2017/1/18.
 * 场景测试类
 */
public class Client {
    public static void main(String [] args){
        TradingStatement ts = new TradingStatement();
        IRMBDeal deal = new IRMBDeal() {
            public String getProvince() {
                return "湖北省";
            }

            public String getCity() {
                return "武汉市";
            }

            public int getRMB() {
                return 100;
            }
        };
        ts.report(deal);
    }
}

此时结果:

交易省份:湖北省
交易城市:武汉市
交易金额(RMB):100

就这样,我们这个交易报表系统用了很久,都挺好,可慢慢公司做大了,在美国开了家分公司,他们也定义了自己的交易类DollarDeal

/**
 * Created by Song on 2017/1/18.
 * 新业务(发生在美国,以美元结算的业务)
 */
public class DollarDeal {
    //交易发生的州
    public String getState(){
        return "Washington State";
    }
   //交易发生的城市
    public String getCity(){
        return "Washington City";
    }
   //交易美金
    public int getDollar(){
        return 100;
    }
}

国内公司在年会的时候呢,也要求我们把美国分公司的报表一起打印出来。可我们原有的报表系统report方法只接收IRMBDeal实例呀,国内交易地点是省份,在美国是州啊,一个用人民币,一个是美金啊,这怎么玩?原来的报表系统一直运行地挺好,改起来也很麻烦(假设),那如何把DollarDeal 实例接入到我们的TradingStatement 报表系统呢?这就回到了文章开始说的接水管的问题了。我们新建一个适配器类,用于将DollarDeal 实例,转换为IRMBDeal实例,RMBDealAdapter 代码如下:

/**
 * Created by Song on 2017/1/18.
 * 适配器类,将DollarDeal实例转化为IRMBDeal实例
 */
public class RMBDealAdapter extends DollarDeal implements IRMBDeal {
    public String getProvince() {
        return super.getState();
    }

    public String getCity() {
        return super.getCity();
    }

    public int getRMB() {
        return super.getDollar()/7;
    }
}

这样,我们在自己的系统中新增加这样一个适配器类,就可以完美地将原本接口不相容的类转换为系统需要的类型,这时,通过适配器打印DollarDeal 的代码为:

/**
 * Created by Song on 2017/1/18.
 * 场景测试类
 */
public class Client {
    public static void main(String [] args){
        TradingStatement ts = new TradingStatement();
        IRMBDeal deal = new RMBDealAdapter();
        ts.report(deal);
    }
}

打印结果为

交易省份:Washington State
交易城市:Washington City
交易金额(RMB):14

上述代码的类图为:
这里写图片描述
从类图上,我们也可以看出,适配器模式实现“适配”功能的主要手段就是继承,在获得不适配类DollarDeal的所有特征之后,通过一定逻辑组合,实现IRMBDeal实例的成员方法。那么如果将DollarDeal分别拆分成交易城市、交易金额等多个不适配类,这是无法同时继承多个类时,如何实现适配器呢?答案是,通过类组合的方式,即在适配类定义交易城市、交易金额等多个不适配类的实例,并通过构造方法或setter方法,将这些实例传进去,其他步骤类似,从而实现适配功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值