JavaRush /Java 博客 /Random-ZH /设计模式适配器

设计模式适配器

已在 Random-ZH 群组中发布
你好!今天我们将触及一个重要的新话题——模式,或者说——设计模式。什么是模式?我想你知道“不要重新发明轮子”这句话。与许多其他领域一样,编程中也存在大量典型情况。对于他们每个人来说,在编程开发过程中,都创建了现成的工作解决方案。这些是设计模式。相对而言,模式是一个特定的例子,它为以下情况提供了解决方案:“如果你的程序需要做某事,如何最好地做它。” 模式有很多,一本优秀的书《学习设计模式》是专门针对它们的,你绝对应该阅读。 设计模式“适配器”- 2简而言之,模式由一个常见问题及其解决方案组成,这已经可以被认为是一种标准。在今天的讲座中,我们将熟悉其中一种称为“适配器”的模式。它的名字就很能说明问题,您在现实生活中不止一次遇到过适配器。最常见的适配器之一是读卡器,许多计算机和笔记本电脑都配备有读卡器。 设计模式“适配器”- 3想象一下我们有某种存储卡。问题是什么? 事实是她不知道如何与计算机交互。它们没有通用的接口。 计算机具有 USB 接口,但无法将存储卡插入其中。该卡无法插入电脑,因此我们将无法保存我们的照片、视频和其他数据。读卡器就是解决这个问题的适配器。毕竟,它有 USB 电缆!与卡本身不同,读卡器可以插入计算机中。它们与计算机有一个共同的接口——USB。让我们通过一个例子来看看它是什么样子的:
public interface USB {

   void connectWithUsbCable();
}
这是我们的USB接口,唯一的方法就是插入USB线:
public class MemoryCard {

   public void insert() {
       System.out.println("Карта памяти успешно вставлена!");
   }

   public void copyData() {
       System.out.println("Данные скопированы на компьютер!");
   }
}
这是我们实现内存映射的类。它已经有我们需要的 2 个方法,但问题是:它没有实现 USB 接口。该卡无法插入 USB 插槽。
public class CardReader implements USB {

   private MemoryCard memoryCard;

   public CardReader(MemoryCard memoryCard) {
       this.memoryCard = memoryCard;
   }

   @Override
   public void connectWithUsbCable() {
       this.memoryCard.insert();
       this.memoryCard.copyData();
   }
}
这是我们的适配器!该类的CardReader作用是什么?为什么它是一个适配器?这很简单。正在适配的类(内存映射)成为适配器的字段之一。这是符合逻辑的,因为在现实生活中我们也会将卡插入读卡器内部,并且它也成为读卡器的一部分。与存储卡不同,适配器具有与计算机的通用接口。它有一根 USB 电缆,这意味着它可以通过 USB 连接到其他设备。因此,在程序中,我们的类CardReader实现了USB接口。但是这个方法内部发生了什么?而我们所需要的正是发生了!适配器将工作委托给我们的存储卡。毕竟,适配器本身不做任何事情;读卡器没有任何独立的功能。它的工作只是链接计算机和存储卡,以便卡可以完成其工作并复制文件!我们的适配器通过connectWithUsbCable()为存储卡的“需求”提供自己的接口(方法)来实现这一点。让我们创建某种客户端程序来模拟想要从存储卡复制数据的人:
public class Main {

   public static void main(String[] args) {

       USB cardReader = new CardReader(new MemoryCard());
       cardReader.connectWithUsbCable();

   }
}
结果我们得到了什么?控制台输出:
Карта памяти успешно вставлена!
Данные скопированы на компьютер!
太好了,我们的任务圆满完成了!以下是一些附加链接,其中包含有关适配器模式的信息:

抽象类 Reader 和 Writer

现在我们将回到我们最喜欢的消遣:我们将学习一些用于处理输入和输出的新课程:)我想知道我们已经学了多少?今天我们来谈谈课程ReaderWriter。为什么是他们呢?因为这会和我们之前的部分——适配器相关。让我们更详细地看看它们。让我们从Reader“a”开始。 Reader是一个抽象类,因此我们无法显式创建它的对象。 但事实上,你已经认识他了!毕竟,您熟悉的类BufferedReaderInputStreamReader它的继承人:)
public class BufferedReader extends Reader {}

public class InputStreamReader extends Reader {}
所以,InputStreamReader是一个经典的适配器。您可能还记得,我们可以将对象传递给其构造函数InputStream。大多数情况下,我们使用变量来实现这一点System.in
public static void main(String[] args) {

   InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
它有什么作用InputStreamReader与任何适配器一样,它将一种接口转换为另一种接口。在这种情况下,接口InputStream'a到接口Reader'a。最初我们有一个班InputStream。它运行良好,但只能读取单个字节。此外,我们还有一个抽象类Reader。它具有我们真正需要的出色功能 - 它可以读取字符!当然,我们确实需要这个机会。但这里我们面临着适配器通常解决的一个经典问题——接口不兼容。它是如何体现出来的?让我们直接看一下 Oracle 文档。以下是类方法InputStreamПаттерн проектирования «Адаптер» - 4一组方法就是一个接口。正如您所看到的,read()此类有一个方法(即使在多个版本中),但它只能读取字节:单个字节或使用缓冲区的多个字节。这个选项不适合我们——我们想要读取字符。我们需要的功能已经在抽象类中实现了Reader。这也可以在文档中看到。 Паттерн проектирования «Адаптер» - 5然而,InputStream“a”和Reader“a”接口不兼容!可以看到,在所有的方法实现中,read()传递的参数和返回值都是不同的。这就是我们需要它的地方InputStreamReader!他将充当我们类之间的适配器。正如我们上面看到的读卡器示例一样,我们“在内部”传递“适配”类的对象,即传递给适配器类的构造函数。在前面的示例中,我们MemoryCard在 内部传递了一个对象CardReader。现在我们将对象传递InputStream给构造函数InputStreamReader!作为一个质量,InputStream我们使用已经熟悉的变量System.in
public static void main(String[] args) {

   InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
事实上:通过查看文档,InputStreamReader我们将看到“适应”是成功的:)现在我们拥有了可以读取字符的方法。 Паттерн проектирования «Адаптер» - 6尽管最初我们的对象System.in(绑定到键盘的线程)不允许这样做,但通过创建适配器模式,该语言的创建者解决了这个问题。Reader与大多数 I/O 类一样,抽象类有一个孪生兄弟 - Writer。它具有同样大的优点Reader- 它提供了一个方便的界面来处理符号。对于输出流,问题及其解决方案看起来与输入流的情况相同。有一个类OutputStream只能写字节;有一个Writer可以使用符号的抽象类,并且有两个不兼容的接口。这个问题再次被Adapter模式成功解决。使用类,OutputStreamWriter我们可以轻松地使两个类接口彼此“适应WriterOutputStream。而且,在构造函数中接收到字节流后OutputStream,在帮助下OutputStreamWriter我们可以写入字符,而不是字节!
import java.io.*;

public class Main {

   public static void main(String[] args) throws IOException {

       OutputStreamWriter streamWriter = new OutputStreamWriter(new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt"));
       streamWriter.write(32144);
       streamWriter.close();
   }
}
我们在文件中写入了一个代码为 32144 - 綐 的字符,从而消除了使用字节的需要:) 今天就这些,我们下节课见!:)
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION