设计模式详解:适配器模式

本文介绍了适配器模式在程序设计中的应用,通过生活中的电源适配器为例,解释了如何通过类适配器和对象适配器模式来解决现有程序与所需功能之间的差异,以提高代码复用性。
摘要由CSDN通过智能技术生成

什么是适配器模式?

在程序设计中,经常会存在一种情况:现有的程序无法直接使用,需要做适当的变换才能使用。

而用于填补“现有程序”和“所需程序”之间差异的设计模式就是适配器模式(Adapter)。 

不理解?没关系,跟你分享一个生活中的例子!

我们在使用笔记本电脑时通常会插上电源,难道我们直接让220v的交流电通到电脑上吗?显然不是。通常,我们会使用AC适配器将家用的220v的交流电转化为电脑所需的直流电。这个就是适配器的工作,位于实际情况与需求之间,填补两者的差异


为什么要使用适配器模式?

那为什么在程序设计中要使用适配器模式呢?答案很简单,为了提高代码的复用性,减少重复开发。


适配器模式如何实现?

适配器模式的实现有两种方式:

  • 类适配器模式(使用继承和接口实现的适配器)
  • 对象适配器模式(使用委托的适配器)

场景描述

下面用一个场景示例来介绍适配器模式的两种实现。

现有一个类Banner和一个接口Print。

Banner类:包含两个方法showWithParen()、showWithAster()。

showWithParen(): 为字符串添加一对括号(),如输入"hello",输出"(hello)"

showWithAster(): 为字符串添加一对**,如输入"hello",输出"*hello*"

Print接口:声明了两种方法printWeak()、printStrong()。

printWeak()方法需要实现功能:为字符串添加一对括号(),如输入"hello",输出"(hello)"
printStrong()方法需要实现功能:为字符串添加一对星号**,如输入"hello",输出"*hello*"

class Banner{
    private String string;

    public Banner(String string){
        this.string = string;
    }

    public void showWithParen(){
        System.out.println("(" + string + ")");
    }

    public void showWithAster(){
        System.out.println("*" + string + "*");
    }
}
interface Print{
    public abstract void printWeak();
    public abstract void printStrong();
}

现在我们需要实现Print接口里的方法,我们应该如何使用适配器模式?


方式一:类适配器模式

编写一个类PrintBanner继承Banner类实现Print接口,在重写printWeak()和printStrong()的时候分别调用Banner类中的showWithParen()和showWithAster()方法。

class PrintBanner extends Banner implements Print{
    public PrintBanner(String string) {
        super(string);
    }

    //我们只需要调用父类Banner中的方法即可
    @Override
    public void printWeak() {
        showWithParen();
    }

    @Override
    public void printStrong() {
        showWithAster();
    }
}

完整代码如下:

/**
 * Author: Jayden
 * Date: 2024/4/1 10:52
 * Version: 1.0
 * Description:
 *      Adapter(适配器)模式有以下两种:
 *          ①类适配器模式(使用继承的适配器)
 *          ②对象适配器模式(使用委托的适配器)
 *
 *
 *      现有:
 *          Banner类:包含两个方法showWithParen()、showWithAster()
 *              showWithParen(): 为字符串添加一对括号(),如输入"hello",输出"(hello)"
 *              showWithAster(): 为字符串添加一对**,如输入"hello",输出"*hello*"
 *
 *          Print接口:声明了两种方法printWeak()、printStrong()
 *
 *
 *      需求:
 *          printWeak()方法需要实现下述功能:
 *              为字符串添加一对括号(),如输入"hello",输出"(hello)"
 *          printStrong()方法需要实现下述功能:
 *              为字符串添加一对星号**,如输入"hello",输出"*hello*"
 *
 *
 *      具体实现:
 *          编写一个类实现Print接口,继承Banner类,在重写printWeak()和printStrong()的时候分别调用Banner类中的showWithParen()和
 *          showWithAster()方法。精髓所在!!避免了代码重复!
 */
public class Demo01 {
    public static void main(String[] args) {
        Print printBanner = new PrintBanner("hello");
        printBanner.printWeak();
        printBanner.printStrong();
    }
}

class Banner{
    private String string;

    public  Banner(String string){
        this.string = string;
    }

    public void showWithParen(){
        System.out.println("(" + string + ")");
    }

    public void showWithAster(){
        System.out.println("*" + string + "*");
    }
}

//我们要做的就是利用现有的代码实现这个接口里的方法,而不是重新写一遍写过的代码
interface Print{
    public abstract void printWeak();
    public abstract void printStrong();
}

class PrintBanner extends Banner implements Print{
    public PrintBanner(String string) {
        super(string);
    }

    //我们只需要调用父类Banner中的方法即可
    @Override
    public void printWeak() {
        showWithParen();
    }

    @Override
    public void printStrong() {
        showWithAster();
    }
}

方式二:对象适配器模式

Banner类不变,Print接口变成抽象类后,我们又该如何处理?

创建一个类PrintBanner继承Print,然后在PrintBanner内部维护一个Banner对象,调用Banner对象中已经实现的showWithPren()和showWithAster()方法即可,用这个对象去调用已实现的方法即为委托。

完整代码如下:

package adapterPattern.pattern02;

/**
 * Author: Jayden
 * Date: 2024/4/1 11:24
 * Version: 1.0
 * Description:
 *      该示例实现对象适配器模式(使用委托的适配器)
 */
public class Demo02 {
    public static void main(String[] args) {
        Print printBanner = new PrintBanner("hello");
        printBanner.printWeak();
        printBanner.printStrong();
    }
}

class Banner{
    private String string;

    public  Banner(String string){
        this.string = string;
    }

    public void showWithParen(){
        System.out.println("(" + string + ")");
    }

    public void showWithAster(){
        System.out.println("*" + string + "*");
    }
}

abstract class Print{
     abstract void printWeak();
     abstract void printStrong();
}


//采用对象适配器模式后,该类的内部会维护一个Banner对象,用这个对象去调用已实现的方法即为委托
class PrintBanner extends Print{
    private Banner banner;

    public PrintBanner(String s){
        this.banner = new Banner(s);
    }

    @Override
    void printWeak() {
        banner.showWithParen();
    }

    @Override
    void printStrong() {
        banner.showWithAster();
    }
}

有人可能会有疑问,为什么main函数中要使用  Print printBanner = new PrintBanner("hello);

而不使用  PrintBanner printBanner = new PrintBanner("hello);

因为示例程序主要想强调Print方法的实现,PrintBanner因为实现了Print接口,继承了Banner类,所以内部会有多种方法。而Print接口中只有printWeak()和printStrong()两种方法,可以更明确地表明程序的意图。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值