Java设计模式之适配器模式(类结构型、对象结构型,双向适配器)

发布于:2023-01-05 ⋅ 阅读:(175) ⋅ 点赞:(0)

1. 适配器模式

注意:代理模式侧重访问控制功能(中介)。适配器模式侧重将适配者类转换成目标接口

生活中经常出现两个对象因接口不兼容而不能一起工作的实例,这时需要第三者进行适配转换。例如讲中文的人同讲英文的人对话时需要一个翻译,用直流电的笔记本电脑接交流电源时需要一个电源适配器

软件设计中也会出现当前系统与某个依赖组件之间接口不兼容,这时用适配器模式能很好地解决这些问题

1.1 定义、优缺点、适用场景

定义:适配器将一个类接口转换成另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,所以应用相对较少些

优点

  • 客户端通过适配器可以透明地调用目标接口
  • 可以直接复用现有的适配者类
  • 将目标接口和适配者类解耦,解决了目标接口和适配者类接口不一致的问题
  • 在很多业务场景中符合开闭原则

缺点

  • 适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性
  • 增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱

适用场景

  • 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致
  • 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同

1.2 模式的结构与实现(类结构型模式)

结构

  • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口
  • 适配者(Adaptee)类:它是已经存在且提供功能的类,但由于接口不兼容,不能被客户端使用
  • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,这样客户就可以按目标接口的格式访问适配器

实现
描述:小明是中国人,只能听懂中国人说的话。有一天来了个只会说英语的英国朋友。所以找来了个翻译,翻译将英语翻译成中文,所以小明能听懂翻译这个中国人说的话

public class AdapterTest {

    public static void main(String[] args) {

        // 翻译为了和小明说话,变成了中国人
        Chinese chinese = new Translater();
        XiaoMing xiaoMing = new XiaoMing();
        xiaoMing.hear(chinese);

    }
}


// 目标接口:中国人
interface Chinese {
    // 说中文
    String speakChinese();
}


class XiaoMing {
    // 小明只能听中国人讲话
    public void hear(Chinese chinese) {
        String chineseWords = chinese.speakChinese();
        System.out.println("小明听懂了中国人说的:" + chineseWords);
    }
}

// 适配者类:真实的英国人
class RealBritish {
    // 说了一句英语
    public String speakEnglish() {
        System.out.println("英国人说了句: hello");
        return "hello";
    }
}

// 适配器类:翻译---对接英国人,进行英语翻译。然后翻译为了和小明说话,变成了中国人
class Translater extends RealBritish implements Chinese {

    // 翻译说中文
    @Override
    public String speakChinese() {
        String englishWords = speakEnglish();
        // 听英国人说的英语,然后转换成中文,再说出去
        System.out.println("翻译将英国人说的:hello,转换成中文:你好");
        return "你好";
    }
}

运行程序,结果如下:

英国人说了句: hello
翻译将英国人说的:hello,转换成中文:你好
小明懂了中国人讲的:你好

1.3 对象结构型模式

修改适配器类和客户端的代码即可,如下所示:

public class AdapterTest {

    public static void main(String[] args) {

        // 翻译对接英国人。翻译为了和小明说话,变成了中国人
        Chinese chinese = new Translater(new RealBritish());
        XiaoMing xiaoMing = new XiaoMing();
        xiaoMing.hear(chinese);

    }
}


// 目标接口:中国人
interface Chinese {
    // 说中文
    String speakChinese();
}


class XiaoMing {
    // 小明只能听中国人讲话
    public void hear(Chinese chinese) {
        String chineseWords = chinese.speakChinese();
        System.out.println("小明听懂了中国人说的:" + chineseWords);
    }
}

// 适配者类:真实的英国人
class RealBritish {
    // 说了一句英语
    public String speakEnglish() {
        System.out.println("英国人说了句: hello");
        return "hello";
    }
}

// 适配器类:翻译---翻译为了和小明说话,变成了中国人
class Translater implements Chinese {
    private RealBritish realBritish;

    // 对接英国人,进行英语翻译
    public Translater(RealBritish realBritish) {
        this.realBritish = realBritish;
    }

    // 翻译说中文
    @Override
    public String speakChinese() {
        String englishWords = this.realBritish.speakEnglish();
        // 听英国人说的英语,然后转换成中文,再说出去
        System.out.println("翻译将英国人说的:hello,转换成中文:你好");
        return "你好";
    }
}

运行程序,结构如下:

英国人说了句: hello
翻译将英国人说的:hello,转换成中文:你好
小明听懂了中国人说的:你好

1.4 双向适配器模式

双向适配器类要么把适配者接口转换成目标接口,要么把目标接口转换成适配者接口。不能同时对适配者接口和目标接口相互转换

public class AdapterTest {

    public static void main(String[] args) {

        British british = new Translater(new RealChinese());
        Tom tom = new Tom();
        tom.hear(british);
        System.out.println("====昨天的一个翻译将中文翻译成英文。今天的另一个翻译将英文翻译成中文======");
        Chinese chinese = new Translater(new RealBritish());
        XiaoMing xiaoMing = new XiaoMing();
        xiaoMing.hear(chinese);

    }
}

// 英文翻译成中文的目标对象
interface Chinese {
    String speakChinese();
}

// 中文翻译成英文的适配者类
class RealChinese implements Chinese {
    @Override
    public String speakChinese() {
        System.out.println("中国人说了句: 你好");
        return "你好";
    }
}


class XiaoMing {
    public void hear(Chinese chinese) {
        String chineseWords = chinese.speakChinese();
        System.out.println("小明听懂了中国人说的:" + chineseWords);
    }
}


// 中文翻译成英文的目标对象
interface British {
    String speakEnglish();
}

// 英文翻译成中文的适配者类
class RealBritish implements British {
    @Override
    public String speakEnglish() {
        System.out.println("英国人说了句: hello");
        return "hello";
    }
}


class Tom {
    public void hear(British british) {
        String englishWords = british.speakEnglish();
        System.out.println("Tom听懂了英国人说的:" + englishWords);
    }
}

// 要么将中文翻译成英文;要么将英文翻译成中文。不能同时翻译中文和英文
class Translater implements Chinese, British {
    private RealChinese realChinese;
    private RealBritish realBritish;

    public Translater(RealChinese realChinese) {
        this.realChinese = realChinese;
    }

    public Translater(RealBritish realBritish) {
        this.realBritish = realBritish;
    }

    @Override
    public String speakEnglish() {
        String chineseWords = this.realChinese.speakChinese();
        System.out.println("翻译将中国人说的:你好,转换成中文:hello");
        return "hello";
    }

    @Override
    public String speakChinese() {
        String englishWords = this.realBritish.speakEnglish();
        System.out.println("翻译将英国人说的:hello,转换成中文:你好");
        return "你好";
    }
}

运行程序,结果如下:

中国人说了句: 你好
翻译将中国人说的:你好,转换成中文:hello
Tom听懂了英国人说的:hello
====昨天的一个翻译将中文翻译成英文。今天的另一个翻译将英文翻译成中文======
英国人说了句: hello
翻译将英国人说的:hello,转换成中文:你好
小明听懂了中国人说的:你好

网站公告

今日签到

点亮在社区的每一天
去签到

热门文章