设计模式:适配器模式

适配器模式(Adapter Pattern)的官方解释:

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

很难理解官方这种说给懂的人听的解释,一般在学习设计模式时,首先疑问最大的就是,什么时候该用到这种设计模式是最合理的呢,我觉得比较直观得还是找出某项目中使用该设计模式,和不使用该设计模式的直接对比,这样理解起来就有一种茅塞顿开的感觉。

客观的解释,适配器模式,就是解决旧的接口和新的接口不兼容的问题,网上看到了一个很好的例子:

一个德国旅馆(Hotel),房间的插座都是两个孔的,一直以来都住的是德国人,德国人的手机充电器都是两个孔的,这样给手机充电就不会发生任何冲突和问题。突然有一天,酒店来了个中国人,中国人的手机充电器却是三个孔的。如果没有适配器,那酒店就得装一个三孔插座,这样就得重新装修,而且每个房间都得装,工作量巨大。于是酒店就想了一个不改变酒店的前提下(开闭原则),解决这个问题的办法:适配器模式。给每个房间装一个适配器,适配器接通两孔插座,适配器本身具有两孔和三孔的功能,就解决了此问题。

之前解释过了,适配器模式是皆苦额新旧不兼容的问题。这里的旧,指的就是德国旅店里的两孔插座,新指的是中国人需要用到的三孔插座。

组装适配器的角色:

对象适配器:

目标接口(或者抽象类)Target:  客户所期待的接口,可以是一个抽象类或接口,也可以是具体类。这里指的是德国插座,这一点解释一下,比较抽象。客户所期待的另一种接口,期待的就是德国插座能够让中国充电器冲上电的接口,但是德国插座是无法给中国充电器使用的,这里旧构成了开头所说的接口不匹配的问题。

需要适配的类(适配者)Adaptee:  需要适配的类,也就是中国插座。

适配器 Adapter:不说也懂吧,通过包装一个适配者,把原接口转换成目标接口。就是把德国插座转为中国插座。

下面用代码来说明一切:

在不使用适配器的情况下:

创建德国旅馆前一定得有德国插座:

public class DGSocket {

    public void insertSocket(){
        System.out.println("插入德国插座");
    }
}

接着创建旅馆:

public class Hotel {

    public void startCharge(DGSocket dgSocket){
        dgSocket.insertSocket();
        System.out.println("开始充电");
    }
}

运行:

public class Test {

    public static void main(String[] args) {
        DGSocket dgSocket = new DGSocket();
        Hotel hotel = new Hotel();
        hotel.startCharge(dgSocket);
    }
}

结果:

过了几年,来了个中国人,因此现在需要中国插座:

public class ZGSocket {
    
    public void insertSocket(){
        System.out.println("插入中国插座");
    }
}

这下适配器就登场了:

public class SocketAdapter extends DGSocket{

    private ZGSocket zgSocket;

    public SocketAdapter(ZGSocket zgSocket) {
        this.zgSocket = zgSocket;
    }

    @Override
    public void insertSocket(){
        zgSocket.insertSocket();
    }
}

这里注意一下,不管是对象适配器还是类适配器,都需要对旧接口做继承或者实现(若就接口是一个类,像上述那样,则无法实现类适配器,应为无法在继承或者实现了,任何对象只有一个父类)。

对象适配器和类适配器的唯一区别:对象适配器是在适配器中增加一个适配者的属性,应为属性可以定义多个,所有可以适配多个适配者。但是继承只能继承一个(继承适配者类),所以类适配器无法适配多个适配者。若是类适配器,旧接口必须为接口,不然无法实现类适配器。

Test类运行:

public class Test {

    public static void main(String[] args) {
        ZGSocket zgSocket = new ZGSocket();
        // 这一步是关键,
        DGSocket dgSocket = new SocketAdapter(zgSocket);
        Hotel hotel = new Hotel();
        hotel.startCharge(dgSocket);
    }
}

运行结果:

这就是官方所说的:从而
使原本因接口不匹配而无法在一起工作的两个类能够在一起工作

类适配器:

若是类适配器,DGSocket 就必须为接口了:

public interface DGSocket {

    // 为了区分和ZG的方法重载的问题,改了下名称
    public void insertDGSocket();
}

适配器:

public class SocketAdapter extends ZGSocket implements DGSocket {

    @Override
    public void insertDGSocket() {
        super.insertSocket();
    }
}

和对象适配器类型显而易见。

Test运行:

public class Test {

    public static void main(String[] args) {
       SocketAdapter adapter = new SocketAdapter();
       Hotel hotel = new Hotel();
       hotel.startCharge(adapter);
    }
}

结果:

总接:

下班了,以后在总结

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值