开发之路(设计模式七:适配器模式)

你眼中的适配器是什么样子的呢?在设计模式中也有模式叫适配器模式,一起来看看吧。         

适配器是什么这不需要作者我多解释把,打个比方,在国内用的是220V的电器,但国外有些国家是110V甚至240V的也有等等,国内的充电线就不能直接插国外的插座了,这时候就需要一个适配器做电源转换,是的,在设计模式中也有这么一个模式与其类似,也是个很有用的模式。

下面我做了几个配图来理解设计模式。

假设已有一个系统,此时它需要更新,你希望它能和新的厂商类库搭配使用,但是这个新厂商设计出来的接口,与原系统的接口不一样。所以两者不能直接匹配。
《开发之路(设计模式七:适配器模式)》

若重构原来的代码可能会非常麻烦,而且又不能去改变厂商的代码,怎么办呢?这是你可以写一个类,将新厂商接口转换为你所期待的接口。
《开发之路(设计模式七:适配器模式)》

那么这个适配器就好比一个中间人,它将客户所发送的请求转换成厂商类能够理解的请求。
《开发之路(设计模式七:适配器模式)》

直接放一个例子,假如一只火鸡想要“冒充”成鸭子怎么做呢?
代码如下:

这是鸭子接口

package duck_Interface;

/**
 * 适配器模式:就好比在中国的电器若要在美国的插座上使用,就必须使用适配器, 
 * 适配器就相当于一个中间层,将两个原本不能相互沟通的东西连接在一起
 * 
 * @author Joy
 * 
 */
public interface Duck {
    public void quack();

    public void fly();
}

绿头鸭是鸭子的子类

package duck_Implements;

import duck_Interface.Duck;

public class MallardDuck implements Duck {
    /**
     * 绿头鸭
     */
    @Override
    public void quack() {
        System.out.println("绿头鸭叫:呱呱呱");

    }

    @Override
    public void fly() {
        System.out.println("我在飞");
    }
}

这是一只火鸡(接口)

package duck_Interface;

/**
 * 火鸡接口
 * 
 * @author Joy
 * 
 */
public interface Turkey {
    // 火鸡只会咯咯咯叫
    public void gobble();

    // 火鸡会飞,但飞不远
    public void fly();
}

这是火鸡的一个具体实现

package duck_Implements;

import duck_Interface.Turkey;

public class WildTurkey implements Turkey {
    /**
     * 火鸡类的实现
     */

    @Override
    public void gobble() {
        System.out.println("火鸡叫:咯咯咯");
    }

    @Override
    public void fly() {
        System.out.println("我会飞,但飞不高");
    }
}

很显然两者一开始不能直接匹配,这里写一个火鸡适配器

package Adapter;

import duck_Interface.Duck;
import duck_Interface.Turkey;

/**
 * 火鸡的适配器
 * 
 * @author Joy
 * 
 */
// 先要实现想要转换的类型接口,(火鸡希望和绿头鸭交流)
// 火鸡:被适配者,鸭子:适配者
// 这里火鸡要实现鸭子接口
public class TurkeyAdapter implements Duck {
    Turkey turkey;

    // 需要取得适配的对象引用
    // 利用构造器取得这个引用
    public TurkeyAdapter(Turkey turkey) {
        this.turkey = turkey;
    }

    @Override
    public void quack() {
        // 现在我们需要实现火鸡里的叫的方法
        // 很简单只需直接引用
        turkey.gobble();
    }

    /**
     * 这里由于火鸡的飞行距离短,鸭子飞行距离长, 为两者飞行能够对应, 这里得多次调用火鸡飞行方法,相当于火鸡5次飞行的距离等于一次鸭子飞行的距离。。
     */
    @Override
    public void fly() {
        for (int i = 0; i < 5; i++) {
            turkey.fly();
        }
    }
}

测试类

package TestMain;

import Adapter.TurkeyAdapter;
import duck_Implements.MallardDuck;
import duck_Implements.WildTurkey;
import duck_Interface.Duck;

public class DuckTestDrive {
    // 取得一只鸭子
    public static void testDuck(Duck duck) {
        duck.quack();
        duck.fly();
    }

    public static void main(String[] args) {
        // 创建好一只鸭子和火鸡
        MallardDuck duck = new MallardDuck();
        WildTurkey turkey = new WildTurkey();
        // 然后将火鸡“包装”进火鸡适配器中,让它看上起像只鸭子
        Duck turkeyAdapter = new TurkeyAdapter(turkey);
        System.out.println("这只火鸡说~~~~~");
        turkey.gobble();
        turkey.fly();
        System.out.println("\n这只鸭子说a~~~~~");
        testDuck(duck);
        // 试着传入一个假装是鸭子的火鸡对象
        System.out.println("\n火鸡适配器说~~~~~");
        /**
         * testDuck()方法不知道这是一只假装鸭子的火鸡 turkey调用叫的方法是“咯咯咯”
         * 而fly方法调用了5次,就为了让火鸡假装成鸭子一样飞的远
         */
        testDuck(turkeyAdapter);

    }
}

效果图
《开发之路(设计模式七:适配器模式)》

TurkeyAdapter里的quack方法被调用,适配器咯咯咯的叫,然后fly方法被调用,适配器执行了5次飞行操作,而在testDuck(Duck duck)它还以为参数duck真的是一鸭子,其实是只假装鸭子的火鸡(turkeyAdapter)。

让我们再看看各部分之间的关系。
《开发之路(设计模式七:适配器模式)》

客户使用适配器的过程如下:
1、客户通过目标接口调用适配器的方法对适配器发出请求。
2、适配器(鸭子)使用被适配器(火鸡)接口把请求转换成被适配器的一个或多个调用接口。
3、客户接收到调用的结果,但并未察觉这一切是适配器再起转换作用。

定义适配器模式:将一个类的接口,转换成客户期待的另一个接口。适配器让原本接口不兼容的类可以合作无间。

注:细分适配器类型是有两种的,对象适配器和类适配器,前面的火鸡例子是对象适配器,而“类”适配器则需要多重继承才能实现,而Java中是不被允许的,这里就不讲述。

感谢你看到这里,适配器模式到这里就结束了,本人文笔随便,若有不足或错误之处望给予指点,90度弯腰~~~很快我会发布下一个设计模式的内容,生命不息,编程不止!

参考书籍:《Head First 设计模式》
    原文作者:设计模式
    原文地址: https://segmentfault.com/a/1190000011102233
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞