본문 바로가기
네이버클라우드/JAVA 웹 프로그래밍

JAVA 27일차 (2023-06-29) 자바 기초 DAY25_자바 프로그래밍_입출력 기능 확장에 상속 대신 Decorator 패턴 적용하기 + Java Stream API 로 교체하기_개인프로젝트 - 마트 관리 시스템

by prometedor 2023. 6. 29.
## 30. 입출력 기능 확장에 상속 대신 Decorator 패턴을 적용하기

- 상속 vs Decorator 패턴(GoF)
  - 기존 코드를 손대지 않고 기능 확장하는 방법
  - 상속: 기능 확장 용이
  - Decorator: 기능 확장 및 기능 제거 용이
- BufferedDataInputStream 분해
  - BufferedInputStream, DataInputStream, FileInputStream
- BufferedDataOutputStream 분해
  - BufferedOutputStream, DataOutputStream, FileOutputStream
  
  ## 31. Java Stream API 로 교체하기

- 입출력 관련 클래스를 자바 스트림 클래스로 교체
  - java.io.* 패키지의 클래스 사용

 

java 17 api 참고

 

 

 

입출력 기능 확장에 상속 대신 Decorator 패턴을 적용하기

DataInputStream 

DataInputStream.java

ㄴ FileInputStream -> InputStream 으로 변경

=> java 17 api 문서에서 확인 시 FileInputStream 은 InputStream 을 상속함

 

DataInputStream.java

ㄴ original 변수 : 기존 InputStream 객체에 대한 참조를 저장하는 데 사용

=> 저장된 original 객체는 DataInputStream 객체 내에서 다양한 작업을 수행하는 데 사용될 수 있음

     ㄴ 예를 들어, DataInputStream 클래스에서 InputStream 객체의 메서드를 호출하거나 추가적인 기능을 구현할 수 있음

          => DataInputStream 클래스는 InputStream 객체의 동작을 확장하거나 재정의할 수 있음

ㄴ 생성자는 InputStream 객체를 매개변수로 받아 original 변수에 할당

 

 

ㄴ InputStream 의 메서드

=> 추상 메서드로 선언되어 있으므로 구현 필요

 

DataInputStream.java

=>

DataInputStream.java

ㄴ read() 메서드를 재정의하여 original.read()를 호출하여 데이터를 읽도록 구현

=> DataInputStream의 read() 메서드를 호출하면 실제로 original 객체의 read() 메서드가 실행되어 데이터를 읽게 됨

ㄴ DataInputStream은 InputStream 클래스의 read() 메서드를 그대로 상속받아 사용

=> DataInputStream은 InputStream 클래스의 기본 동작을 그대로 유지하면서, 추가적인 기능을 구현하거나 수정할 수 있음

 

ㄴ InputStream 의 메서드

 

DataInputStream.java

=>

DataInputStream.java

ㄴ DataInputStream의 read(byte[] b) 메서드를 호출하면 실제로 original 객체의 read(byte[] b) 메서드가 실행되어 데이터를 b 배열에 읽게 됨

ㄴ DataInputStream은 InputStream 클래스의 read(byte[] b) 메서드를 그대로 상속받아 사용

=> DataInputStream은 InputStream 클래스의 기본 동작을 그대로 유지하면서, 추가적인 기능을 구현하거나 수정할 수 있음

 

=> read() 메서드는 InputStream 클래스에서 추상 메서드로 선언되어 있으며, DataInputStream 클래스는 InputStream 클래스를 상속하고 있어서 DataInputStream 클래스에서는 read() 메서드를 반드시 구현해야 하지만, read(byte[] b) 메서드는 InputStream 클래스에 존재하고 추상 메서드도 아니므로 제거해도 됨

 

DataInputStream.java

=>

DataInputStream.java

ㄴ DataInputStream 클래스에서 close() 메서드를 오버라이딩

=> InputStream의 close() 메서드는 입력 스트림을 닫고 사용한 자원을 해제하는 역할을 함

=> 파일이나 네트워크 등의 입력 소스와의 연결을 종료하고, 관련된 자원들을 정리함

 

DataOutputStream 

DataOutputStream.java

ㄴ original 변수 : 기존 OutputStream 객체에 대한 참조를 저장하는 데 사용

=> 저장된 original 객체는 DataOutputStream 객체 내에서 다양한 작업을 수행하는 데 사용될 수 있음

     ㄴ 예를 들어, DataOutputStream 클래스에서 OutputStream 객체의 메서드를 호출하거나 추가적인 기능을 구현할 수 있음

          => DataOutputStream 클래스는 OutputStream 객체의 동작을 확장하거나 재정의할 수 있음

ㄴ 생성자는 OutputStream 객체를 매개변수로 받아 original 변수에 할당

 

 

DataOutputStream.java

=>

DataOutputStream.java

ㄴ write(int b) 메서드는 OutputStream 클래스의 추상 메서드를 재정의한 것

ㄴ  int 형식의 파라미터 b를 받아서 데이터를 출력함

ㄴ 메서드 내부에서는 original.write(b)를 호출하여 original 객체를 통해 데이터를 출력하도록 구현

=> DataOutputStream 클래스는 외부로부터 전달받은 original 객체를 사용하여 데이터를 출력함

 

DataOutputStream.java

=>

DataOutputStream.java

ㄴ flush() 메서드는 출력 스트림에 남아있는 모든 데이터를 강제로 출력함

ㄴ 버퍼에 저장된 데이터를 출력 소스로 모두 전송하고, 버퍼를 비우는 역할을 함

=> 이를 통해 데이터의 일부가 버퍼에만 남아있는 상황을 방지하고, 데이터의 신뢰성과 일관성을 유지할 수 있음

 

DataOutputStream.java

=>

DataOutputStream.java

ㄴ DataInputStream 클래스에서 close() 메서드를 오버라이딩
ㄴ close() 메서드는 출력 스트림을 닫고 사용한 자원을 해제함

ㄴ flush() 메서드를 호출하여 남은 데이터를 출력한 후, 출력 소스와의 연결을 종료하고 관련된 자원을 정리함

 

App.java

ㄴ FileInputStream을 사용하여 member.data 파일을 읽기 위한 스트림인 in0을 생성

ㄴ 이 in0 스트림을 DataInputStream의 생성자에 전달하여 in 스트림을 생성

=> DataInputStream을 사용하여 파일에서 데이터를 읽을 수 있게 됨

 

App.java

ㄴ Item 도 Member 와 동일한 방식

 

App.java

ㄴ Board 도 Item, Member 와 동일한 방식

 

 

App.java

ㄴ FileOutputStream을 사용하여 member.data 파일에 데이터를 쓰기 위한 스트림인 out0을 생성

ㄴ 이 out0 스트림을 DataOutputStream의 생성자에 전달하여 out 스트림을 생성

=> DataOutputStream을 사용하여 데이터를 파일에 쓸 수 있게 됨

 

ㄴ FileOutputStream은 "member.data" 파일에 대한 출력 스트림을 생성하기 위한 클래스임

ㄴ 파일이 존재하지 않으면 새로운 파일이 생성되며, 파일이 이미 존재한다면 그 파일에 데이터를 추가하여 쓸 수 있음

ㄴ FileOutputStream은 바이트 단위로 데이터를 파일에 쓰는 기능을 제공

 

App.java

ㄴ FileOutputStream out0 = new FileOutputStream("member.data"); 코드는 "member.data" 파일에 대한 FileOutputStream 객체를 생성함 => 이 객체는 파일에 데이터를 출력하는 역할을 함
ㄴ DataOutputStream out = new DataOutputStream(out0); 코드는 out0에 대한 DataOutputStream 객체를 생성함

=> 이 객체는 FileOutputStream을 감싸고 있으며, 데이터를 다양한 형식으로 변환하여 out0에 출력할 수 있는 기능을 제공함

 

=> Member 와 동일하게 Item, Board 에도 적용해주기

 

App.java

ㄴ FileOutputStream out0 = new FileOutputStream("item.data"); 코드는 "item.data" 파일에 대한 FileOutputStream 객체를 생성함 => 이 객체는 파일에 데이터를 출력하는 역할을 함
ㄴ DataOutputStream out = new DataOutputStream(out0); 코드는 out0에 대한 DataOutputStream 객체를 생성함

=> 이 객체는 FileOutputStream을 감싸고 있으며, 데이터를 다양한 형식으로 변환하여 out0에 출력할 수 있는 기능을 제공함

App.java

ㄴ FileOutputStream out0 = new FileOutputStream("board.data"); 코드는 "board.data" 파일에 대한 FileOutputStream 객체를 생성함 => 이 객체는 파일에 데이터를 출력하는 역할을 함
ㄴ DataOutputStream out = new DataOutputStream(out0); 코드는 out0에 대한 DataOutputStream 객체를 생성함

=> 이 객체는 FileOutputStream을 감싸고 있으며, 데이터를 다양한 형식으로 변환하여 out0에 출력할 수 있는 기능을 제공함

 

App.java

ㄴ BufferedDataInputStream -> BufferedInputStream

ㄴ BufferedDataOutputStream -> BufferedOutputStream

 

BufferedInputStream.java

ㄴ FileInputStream -> InputStream 으로 변경

=> java 17 api 문서에서 확인 시 BufferedInputStream 은 InputStream 을 상속함

 

BufferedInputStream.java

ㄴ original 변수 : 기존 InputStream 객체에 대한 참조를 저장하는 데 사용

 

BufferedInputStream.java

ㄴ 생성자는 InputStream 객체를 매개변수로 받아 original 변수에 할당

 

BufferedInputStream.java

ㄴ super -> original 로 변경

 

BufferedInputStream.java

ㄴ read(byte[] arr) 메서드 주석처리 해두기

 

BufferedInputStream.java

ㄴ super -> original 로 변경

 

 

BufferedOutputStream.java

ㄴ original 변수 : 기존 InputStream 객체에 대한 참조를 저장하는 데 사용

ㄴ 생성자는 InputStream 객체를 매개변수로 받아 original 변수에 할당

 

BufferedOutputStream.java

ㄴ super -> original 로 변경

 

BufferedOutputStream.java

ㄴ super -> original 로 변경

 

App.java

ㄴ BufferedOutputStream 적용

ㄴBufferedOutputStream 과 DataOutputStream 모두 Decorator(장식품) 역할을 함

=> 상속과 달리 제거 및 추가가 용이함

 

=> saveItem(), saveBoard() 메서드에 모두 동일하게 적용해주기

=> LoadMember(), LoadItem(), LoadBoard() 메서드는 BufferedInputStream 적용해주기

 

 

Java Stream API 로 교체하기

java.io.* 패키지의 클래스 사용

ㄴ 생성했던 bitcamp.io 패키지 제거

 

App.java

ㄴ [command] + [shift] + O 이용하여 Java Stream API 로 교체