CodeGym /Java 博客 /随机的 /适配器设计模式
John Squirrels
第 41 级
San Francisco

适配器设计模式

已在 随机的 群组中发布
你好!今天我们将讨论一个重要的新话题:设计模式。这些图案是什么?我想你一定知道“不要重新发明轮子”这句话。在编程中,与许多其他领域一样,存在大量常见情况。随着软件开发的发展,已经为它们中的每一个创建了现成的解决方案。这些解决方案称为设计模式。按照惯例,模式是这样制定的一些解决方案:“如果您需要在程序中执行 X,那么这是执行此操作的最佳方式”。有很多图案。您绝对应该熟悉的优秀书籍《Head First Design Patterns》就是献给他们的。 适配器设计模式 - 2简而言之,一个模式由一个常见问题和一个相应的解决方案组成,可以认为是一种标准。在今天的课程中,我们将遇到其中一种模式:适配器。顾名思义,您在现实生活中已经多次遇到适配器。一些最常见的适配器是许多计算机和笔记本电脑都有的读卡器。 适配器设计模式 - 3假设我们有某种存储卡。所以有什么问题? 它不知道如何与计算机交互。它们不共享通用接口。 电脑有USB接口,但是我们不能把内存卡插进去。卡无法插入电脑,所以我们无法保存我们的照片、视频和其他数据。读卡器就是解决这个问题的适配器。毕竟,它有 USB 数据线!与卡本身不同,读卡器可以插入计算机。它们与计算机共享一个通用接口:USB。让我们看看这在实践中是怎样的:

public interface USB { 

   void connectWithUsbCable(); 
}
这是我们的 USB 接口,只有一种通过 USB 连接的方法。

public class MemoryCard { 

   public void insert() { 
       System.out.println("Memory card successfully inserted!"); 
   } 

   public void copyData() { 
       System.out.println("The data has been copied to the computer!"); 
   } 
}
这是我们代表存储卡的类。它已经有了我们需要的 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类做什么,究竟是什么使它成为适配器?一切都很简单。正在适配的类 (MemoryCard) 成为适配器的字段之一。这是有道理的。当我们在现实生活中将存储卡放入读卡器时,它也成为其中的一部分。与存储卡不同,适配器与计算机共享一个接口。它有一根 USB 电缆,即它可以通过 USB 连接到其他设备。这就是我们的 CardReader 类实现 USB 接口的原因。但是这个方法内部究竟发生了什么?正是我们需要发生的事情!适配器将工作委托给我们的存储卡。实际上,适配器本身不执行任何操作。读卡器没有任何独立的功能。它的工作只是连接电脑和记忆卡,让记忆卡做它的工作——复制文件!connectWithUsbCable()方法)来满足存储卡的“需要”。让我们创建一些客户端程序来模拟一个想要从存储卡复制数据的人:

public class Main { 

   public static void main(String[] args) { 

       USB cardReader = new CardReader(new MemoryCard()); 
       cardReader.connectWithUsbCable(); 
   } 
}
那么我们得到了什么?控制台输出:

Memory card successfully inserted! 
The data has been copied to the computer!
出色的。我们达到了目的!下面是一个视频链接,其中包含有关适配器模式的信息:

Reader 和 Writer 抽象类

现在我们将回到我们最喜欢的活动:了解几个处理输入和输出的新类 :) 我想知道我们已经了解了多少。今天我们将讨论类Reader 和Writer类。为什么特别是那些类?因为它们与我们之前关于适配器的部分有关。让我们更详细地研究它们。我们将从 Reader. 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接口到Reader接口。最初,我们有这个InputStream类。它运行良好,但您只能使用它来读取单个字节。此外,我们还有一个Reader抽象类。它有一些非常有用的功能——它知道如何阅读字符!我们当然需要这种能力。但在这里,我们面临通常由适配器解决的经典问题——不兼容的接口。这意味着什么?让我们看一下 Oracle 文档。下面是类的方法InputStream适配器设计模式 - 4一组方法就是接口。正如你所看到的,这个类有一个read()方法(实际上有几个变体),但它只能读取字节:单个字节或使用缓冲区的几个字节。但是这个选项不适合我们——我们想要读取字符。我们需要已经在Reader抽象类中实现的功能。我们也可以在文档中看到这一点。 适配器设计模式 - 5但是,InputStream和 Reader接口不兼容!如您所见,该read()方法的每个实现都有不同的参数和返回值。这就是我们需要的地方InputStreamReader!它将充当我们类之间的适配器。 与我们上面考虑的读卡器示例一样,我们将被适配类的一个实例放在适配器类“内部”,即我们将一个实例传递给它的构造函数。在前面的例子中,我们MemoryCard在里面放了一个对象CardReader。现在我们将一个InputStream 对象传递给InputStreamReader构造函数!我们使用我们熟悉的System.in变量作为InputStream

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
事实上,查看 的文档InputStreamReader,我们可以看到改编成功了 :) 现在我们有了读取字符的方法供我们使用。 适配器设计模式 - 6尽管我们的System.in对象(绑定到键盘的流)最初不允许这样做,但该语言的创建者通过实施适配器模式解决了这个问题。Reader与大多数 I/O 类一样,抽象类有一个孪生兄弟 — Writer. 它有同样大的优势 Reader ——它提供了一个方便的界面来处理角色。对于输出流,问题及其解决方案看起来与输入流相同。有一个OutputStream只能写字节的类,有一个Writer知道如何处理字符的抽象类,并且有两个不兼容的接口。这个问题又一次被适配器模式解决了。我们使用类来轻松地使 和 类OutputStreamWriter的两个接口 相互适配。将字节流传递给构造函数后,我们可以使用 an来写入字符而不是字节! WriterOutputStreamOutputStreamOutputStreamWriter

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