JavaRush /Java Blog /Random-KO /디자인 패턴 어댑터

디자인 패턴 어댑터

Random-KO 그룹에 게시되었습니다
안녕하세요! 오늘 우리는 중요한 새로운 주제인 패턴, 즉 디자인 패턴을 다룰 것입니다 . 패턴이란 무엇입니까? “바퀴를 재발명하지 마세요”라는 표현을 아실 것 같아요. 다른 많은 영역과 마찬가지로 프로그래밍에도 일반적인 상황이 많이 있습니다. 각각에 대해 프로그래밍 개발 과정에서 기성 작업 솔루션이 만들어졌습니다. 이것은 디자인 패턴입니다. 상대적으로 말하면, 패턴은 "프로그램에서 어떤 작업을 수행해야 한다면 최선의 방법은 무엇입니까?"와 같은 상황에 대한 솔루션을 제공하는 특정 예입니다. 많은 패턴이 있으며, 반드시 읽어야 할 훌륭한 책인 "Studying Design Patterns"에 헌정되어 있습니다. 디자인 패턴 "어댑터" - 2최대한 간략하게 말하면, 패턴은 공통적인 문제와 그에 대한 해결책으로 구성되며, 이는 이미 일종의 표준이라고 볼 수 있습니다. 오늘 강의에서는 이러한 패턴 중 "Adapter"라는 패턴에 대해 알아 보겠습니다. 이름에서 알 수 있듯이 실제 생활에서 어댑터를 두 번 이상 접해 본 적이 있을 것입니다. 가장 일반적인 어댑터 중 하나는 많은 컴퓨터와 노트북에 장착된 카드 리더입니다. 디자인 패턴 "어댑터" - 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("Данные скопированы на компьютер!");
   }
}
이것은 메모리 맵을 구현하는 클래스입니다. 필요한 두 가지 방법이 이미 있지만 여기에 문제가 있습니다. 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를 통해 다른 장치에 연결할 수 있습니다. 따라서 프로그램에서 우리 클래스는 CardReaderUSB 인터페이스를 구현합니다. 하지만 이 메서드 내부에서는 어떤 일이 발생하나요? 그리고 우리에게 꼭 필요한 일이 일어났습니다! 어댑터는 작업을 메모리 카드에 위임합니다. 결국 어댑터 자체는 아무 작업도 수행하지 않으며 카드 리더기에는 독립적인 기능이 없습니다. 그 역할은 컴퓨터와 메모리 카드를 연결하여 카드가 해당 작업을 수행하고 파일을 복사할 수 있도록 하는 것입니다! connectWithUsbCable()우리의 어댑터는 메모리 카드의 "필요"에 맞는 자체 인터페이스(메서드)를 제공함으로써 이를 수행할 수 있습니다 . 메모리 카드에서 데이터를 복사하려는 사람을 시뮬레이션하는 일종의 클라이언트 프로그램을 만들어 보겠습니다.
public class Main {

   public static void main(String[] args) {

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

   }
}
그 결과 우리는 무엇을 얻었습니까? 콘솔 출력:
Карта памяти успешно вставлена!
Данные скопированы на компьютер!
좋습니다. 우리의 작업이 성공적으로 완료되었습니다! 다음은 어댑터 패턴에 대한 정보가 포함된 몇 가지 추가 링크입니다.

추상 클래스 리더 및 라이터

이제 우리는 우리가 가장 좋아하는 취미로 돌아갈 것입니다. 우리는 입력 및 출력 작업을 위한 몇 가지 새로운 클래스를 배울 것입니다. :) 우리는 이미 그 중 몇 개를 배웠는지 궁금합니다. Reader오늘은 클래스 와 에 대해 이야기하겠습니다 Writer. 그 사람들은 왜요? 이는 이전 섹션인 어댑터와 관련이 있기 때문입니다. 좀 더 자세히 살펴보겠습니다. 'a' 부터 시작해보자 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'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(키보드에 바인딩된 스레드)가 이를 허용하지 않았지만 언어 작성자는 어댑터 패턴을 생성하여 이 문제를 해결했습니다. 대부분의 I/O 클래스와 마찬가지로 추상 클래스에는 Reader쌍둥이 형제가 있습니다 Writer. 동일한 큰 장점이 있습니다 Reader. 기호 작업에 편리한 인터페이스를 제공한다는 것입니다. 출력 스트림의 경우 문제와 해결 방법은 입력 스트림의 경우와 동일하게 보입니다. OutputStream바이트만 쓸 수 있는 클래스가 있습니다 . 기호로 작업할 수 있는 추상 클래스가 있고 Writer호환되지 않는 인터페이스가 두 개 있습니다. 이 문제는 Adapter 패턴으로 다시 성공적으로 해결되었습니다. 클래스를 사용하면 두 클래스 인터페이스를 서로 OutputStreamWriter쉽게 "적응"할 수 있습니다 . 그리고 생성자에서 바이트 스트림을 수신하면 바이트가 아닌 문자를 쓸 수 있습니다! 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