适配器模式

       适配器相信大家都见过,我们使用的电脑的电源插头就会有一个适配器,在交流电和电脑之间做一个桥接和电流转换;如果你要去国外,国外的插座和你的电器的插头不匹配,但是你还是想使用自己的电器,怎么办呢?这就可以使用适配器,在国内的插头与国外的插座之间做桥接,达到电器使用的目的。换句话说,就是给电器的接口转化成了另一个接口。来,我们看定义:适配器模式是将一个类的接口,转换成客户期望的另一个接口,让原来不兼容的类可以合作无间。

        现在我们回到适配器模式上,为什么需要适配器模式呢?假如我们有一个软件系统,需要和其他厂商的软件系统搭配使用,两个系统都已经设计好了,但是暴露出来的api不一致,这时候我们不愿意修改原来的代码,当然厂商的代码更是无法修改(修改权在厂商手中,它们是api的定义者,当然它们觉得,第三方使用它们的产品,当然得按照它们的接口定义来),这时候我们该怎么办呢?大家应该可以想到,跟现实生活的例子结合在一起就很明白,插头和插口不一致,而两者又不可变,那么久可以做出来一个适配器使得插头和插口完美结合在一起,同样的,若两个软件系统的调用方和被调用方不匹配,我们也可以做出一个适配器类来衔接两者。

        我们再换个立场来思考,假如我们的软件系统被别人调用,但是我们需要修改接口,但又不希望希望一一通知我们的客户让他们修改,即如果我们要做到客户对我们的修改无感知,那么就需要适配器类,这可以让客户从实现的接口解耦,适配器可以将改变的部门封装起来,这样客户就不必为了应付不同的接口而每次跟着修改。

下面来看例子:

/**
 * 华为手机
 */
public class HuaweiPhone {

    ChinaSocket socket;

    public HuaweiPhone(ChinaSocket socket){
        this.socket = socket;
    }

    public void gainElec() {
        socket.charge();
    }
}
/**
 * 中国插座
 */
public interface ChinaSocket {

    public void charge220V();
}
/**
 * 公牛
 */
public class Bull implements ChinaSocket{

    public void charge220V() {
        System.out.println("用220V的电压充电");
    }
}

       我们有一个华为手机,可以通过输出电压为220V中国标准的公牛插座充电,完全ok。

/**
 * 有一部华为手机和一个公牛插座
 */
public class ChinaMain {

    public static void main(String[] args) {
        ChinaSocket socket = new Bull();

        HuaweiPhone huaweiPhone = new HuaweiPhone(socket);

        huaweiPhone.gainElec();
    }
}

运行结果:

用220V的电压充电

Process finished with exit code 0

 

但是假如现在我们在欧洲,我们有华为手机和欧洲插座abc

**
 * 华为手机
 */
public class HuaweiPhone {

    ChinaSocket socket;

    public HuaweiPhone(ChinaSocket socket){
        this.socket = socket;
    }

    public void gainElec() {
        socket.charge220V();
    }
}
/**
 * 欧洲插座
 */
public interface EuropeSocket {

    public void charge110V();
}
/**
 * 欧洲某一品牌的插座
 */
public class abc implements EuropeSocket {

    public void charge110V() {
        System.out.println("用110V电压充电");
    }
}

这样肯定是不能使用的。。

现在我们想给华为手机充电,就可以找一个适配器

/**
 * 适配器
 */
public class SocketAdapter implements ChinaSocket{

    EuropeSocket eSocket;

    public SocketAdapter(EuropeSocket eSocket){
        this.eSocket = eSocket;
    }

    public void charge220V() {
        System.out.println("下面是欧洲的充电标准");
        eSocket.charge110V();
        System.out.println("将欧洲标准转化为中国标准:220V");
    }
}

该适配器对外暴露的是中国标准,而内部包装的是欧洲标准,适配器可以对已有的电压进行转换,通过它,我们就可以给华为手机充电了,如下:

/**
 * Created by anxufeng on 2019/5/22
 */
public class Main {

    public static void main(String[] args) {

        EuropeSocket eSocket = new abc();       //有一欧洲标准的abc品牌插座

        ChinaSocket socket = new SocketAdapter(eSocket);  //适配器对欧洲插座包装并转换电压

        HuaweiPhone huaweiPhone = new HuaweiPhone(socket);  //华为手机可以用适配器充电

        huaweiPhone.gainElec();
    }
}

运行结果:

下面是欧洲的充电标准
用110V电压充电
将欧洲标准转化为中国标准:220V

Process finished with exit code 0

       适配器模式使用与原来的两个系统的代码已经完成,并想将甲乙两个系统配合使用,但是定义的api不一致,又无法改变或不想改变原来代码就可以使用的情况。若是在开发过程中或开发前,那么调用方完全可以按照被调用方的接口设计来开发,而避免使用适配器模式。 

       可能很多同学对装饰器模式和适配器模式比较混淆,它们的区别是这样的:装饰模式包装的是自己的兄弟类,隶属于同一个家族(相同接口或父类),适配器模式则修饰非血缘关系类,把一个非本家族的对象伪装成本家族的对象,注意是伪装,因此它的本质还是非相同接口的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值