やあ!今日は、重要な新しいトピック「デザイン パターン」について触れます。これらのパターンは何ですか? 「車輪の再発明はしない」という言葉をご存知かと思います。他の多くの分野と同様、プログラミングにも、一般的な状況が多数あります。ソフトウェア開発が進化するにつれて、それぞれに適した既製のソリューションが作成されてきました。これらのソリューションはデザイン パターンと呼ばれます。慣習的に、パターンとは、「プログラムで X を実行する必要がある場合、これを行うための最良の方法である」というように定式化されたソリューションです。たくさんのパターンがあります。これらについては、ぜひよく知っておくべき優れた本『Head First Design Patterns』を参照してください。 簡潔に言うと、パターンは、一種の標準とみなせる、共通の問題とそれに対応する解決策で構成されます。今日のレッスンでは、これらのパターンの 1 つであるアダプターについて説明します。名前がすべてを物語っていて、現実の生活でもアダプターに何度も遭遇したことがあります。最も一般的なアダプタには、多くのコンピュータやラップトップに搭載されているカード リーダーがあります。 ある種のメモリカードがあるとします。だから問題は何ですか? コンピュータと対話する方法を知りません。これらは共通のインターフェイスを共有していません。 コンピュータには USB ポートがありますが、メモリ カードを挿入できません。カードをコンピュータに接続できないため、写真、ビデオ、その他のデータを保存できません。カードリーダーはこの問題を解決するアダプターです。なんといってもUSBケーブルが付いているからです!カード自体とは異なり、カード リーダーはコンピューターに接続できます。これらはコンピュータと共通のインターフェイスである USB を共有します。これが実際にどのようになるかを見てみましょう。
public interface USB {
void connectWithUsbCable();
}
これは、USB 経由で接続するための 1 つの方法だけを備えた 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) はアダプターのフィールドの 1 つになります。意味あり。実際にメモリカードをカードリーダーに入れると、メモリカードもカードリーダーの一部になります。メモリ カードとは異なり、アダプタはコンピュータとインターフェイスを共有します。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
は抽象クラスであるため、オブジェクトを明示的に作成することはできません。 しかし、実際にはすでによくご存知です。結局のところ、あなたはその子孫である BufferedReader
およびクラスについてよく知っています:)InputStreamReader
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
。 メソッドのセットはまさにインターフェイスそのものです。ご覧のとおり、このクラスにはread()
このメソッド (実際にはいくつかのバリエーション) を使用できますが、読み取ることができるのはバイトのみです。個々のバイト、またはバッファを使用した複数バイトのいずれかです。しかし、このオプションは私たちには適していません。私たちは文字を読みたいのです。抽象クラスにすでに実装されているReader
機能が必要です。これはドキュメントでも確認できます。 ただし、InputStream
と の Reader
インターフェイスには互換性がありません。ご覧のとおり、read()
メソッドの実装ごとに異なるパラメーターと戻り値があります。そしてここが私たちが必要とするところですInputStreamReader
!これはクラス間の アダプターとして機能します。上で検討したカード リーダーの例と同様に、適応されるクラスのインスタンスをアダプター クラスの「内部」に置きます。つまり、インスタンスをそのコンストラクターに渡します。前の例では、MemoryCard
オブジェクトを の中に入れましたCardReader
。InputStream
次に、オブジェクトをコンストラクターに渡しますInputStreamReader
。おなじみのSystem.in
変数を次のように使用しますInputStream
。
public static void main(String[] args) {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
そして実際、 のドキュメントを見るとInputStreamReader
、適応が成功したことがわかります :) これで、自由に文字を読み取るメソッドができました。 そして、私たちのSystem.in
オブジェクト (キーボードにバインドされたストリーム) は当初これを許可していませんでしたが、言語の作成者はアダプター パターンを実装することでこの問題を解決しました。Reader
ほとんどの I/O クラスと同様、抽象クラスには双子の兄弟 ( ) があり ますWriter
。これには、キャラクターを操作するための便利なインターフェイスが提供されるという大きな利点もあります Reader
。出力ストリームの場合、問題とその解決策は入力ストリームの場合と同じように見えます。OutputStream
バイトしか書き込めないクラスがあります。Writer
文字の操作方法を認識する抽象クラスと、互換性のないインターフェイスが 2 つあります。この問題もアダプター パターンによって解決されます。クラスを使用して、 と クラスOutputStreamWriter
の 2 つのインターフェイスを 相互に簡単に適合させます。バイト ストリームをコンストラクターに渡した後、 を使用してバイトではなく文字を書き込むことができます。 Writer
OutputStream
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 (綐) の文字をファイルに書き込んだので、バイトを扱う必要がなくなりました :) 今日はここまでです。次のレッスンでお会いしましょう!:)
GO TO FULL VERSION