Head First设计模式读书笔记六 第七章上 适配器模式

本文示例代码材料源自Head First设计模式
以前整理自己整理的链接:
https://blog.csdn.net/u011109881/article/details/58261956

思想

要了解适配器模式,就得先了解什么是适配器,百度百科的定义如下:

适配器是一个接口转换器,它可以是一个独立的硬件接口设备,允许硬件或电子接口与其它硬件或电子接口相连,也可以是信息接口。比如:电源适配器、三角架基座转接部件、USB与串口的转接设备等。

适配器看上去好像不太好懂,那么我说另一个名词:转接口呢?个人觉得,适配器模式的原理就和转接口差不多,比如普通的耳机无法连接iPhone,但是加根转接线就好了,普通的USB线无法给type C接口的手机充电,但是加个转接口就好啦。说到底,适配器就是当某个东西不满足当前条件时,我们通过一个转换对象,使得这个东西满足条件。我觉得Head First设计模式的图解还是很生动的。
摘自Head First设计模式

情景再现

现在我们有鸭子类的接口和具体实现类如下:

public interface Duck {
    public void quack();
    public void fly();
}
public class MollardDuck implements Duck{

    public void quack() {
        System.out.println("MollardDuck quack");
    }

    public void fly() {
        System.out.println("MollardDuck flying");
    }

}

我们还有另外一个物种,火鸡及其实现类

public interface Turkey {
    public void gobble();
    public void fly();
}
public class WildTurkey implements Turkey {

    public void gobble() {
        System.out.println("WildTurkey goggle");
    }

    public void fly() {
        System.out.println("WildTurkey fly");
    }

}

现在假设我们缺少鸭子对象,要拿火鸡来充数。(因为鸭子和火鸡还是存在很多类似的部分的,两个大相径庭的事物是不能使用适配器的。)要如何做呢?
那就得实现一个适配器。

public class TurkeyToDuckAdapter implements Duck{
    Turkey turkey;
    public TurkeyToDuckAdapter(Turkey turkey) {
        this.turkey = turkey;
    }

    public void quack() {
        turkey.gobble();
    }

    public void fly() {
        //由于火鸡飞的很近,要像鸭子飞的那么远要飞五次,所以这里需要调用5次
        for(int i =0;i<5;i++){
            turkey.fly();
        }
    }

}

适配器或者转接口会生效么?先看看测试类:

public class Test {

    public static void main(String[] args) {
        List<Duck> ducks = new ArrayList<Duck>();
        Duck mllardDuck = new MollardDuck();
        ducks.add(mllardDuck);
        Turkey wildTurkey = new WildTurkey();
        Duck wildTurkeyDuck = new TurkeyToDuckAdapter(wildTurkey);
        ducks.add(wildTurkeyDuck);

        Iterator<Duck> iterator = ducks.iterator();
        while(iterator.hasNext()){
            testDuck(iterator.next());
        }

    }

    static void testDuck(Duck duck){
        duck.fly();
        duck.quack();
    }

}

ducks的列表中是无法加入turkey的,因为泛型规定,只能加入Duck类型的物种。但是有了适配器或者转接口,就可以把火鸡伪装成鸭子,加入鸭子的列表。甚至瞒过testDuck方法的眼睛。
测试结果:

MollardDuck flying
MollardDuck quack
WildTurkey fly
WildTurkey fly
WildTurkey fly
WildTurkey fly
WildTurkey fly
WildTurkey goggle

几点拓展

适配器的工作量:
增加一个适配的工作量和适配对象的复杂度成正比,比如鸭子和火鸡,本身都很简单,因此适配很简单。但试想一下,如果两者都很复杂,比如Duck接口有20几个方法,那么适配器势必都要实现这20个方法,因此复杂度和接口复杂度成正比
适配器可以封装多个类么:
我觉得可以通过实现多个接口来实现。
装饰器和适配器对比:
两者都是将对象进行封装,只不过目的不同。装饰器的包装是为了给原先的对象添加一种新的功能。而适配器的目的是将一个对象包装成像另一种对象的样子,以达到符合接口要求的目的。
类适配器和对象适配器
主要区别就是实现方式类适配器通过继承实现,而对象适配器通过实现接口实现。本文中的例子就是一个对象适配器。如果将Duck由接口改成class,那么适配器就会变成类适配器。书中列出了许多两者的区别,但个人觉,他们的区别并不是很大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值