220620_인터넷 강의_직렬화 / 여러 가지 스트림 / 데코레이터 패턴

창고·2022년 10월 21일
0

티스토리에 저장했던 글을 옮겼습니다.
https://mrcocoball.tistory.com/94

1. 직렬화 (Serialization)

(1) 직렬화의 정의

  • 인스턴스의 상태를 그대로 파일 저장 / 네트워크 전송 (Serialization, 직렬화), 다시 복원(Deserialization) 하는 방식
  • 보조 스트림을 활용하여 직렬화 제공
    • ObjectInputStream(InputStream in) : InputStream을 매개변수로 받아 ObjectInputStream 생성
    • ObjectOutputStream(OutputStream in) : OutputStream을 매개변수로 받아 ObjectOutputStream 생성

(2) Serialization 인터페이스

  • 인스턴스의 내용이 외부로 유출되는 것이기에 프로그래머가 해당 객체에 대한 직렬화 의도 표시가 필요 (implements Serializable)
  • transient : 직렬화 하지 않으려는 멤버 변수에 사용
class Person implements Serializable { // 직렬화를 위해 직렬화 의도를 Serializable을 구현함으로써 드러냄
	
	String name;
	String job;
	// transient String job; // 직렬화 하지 않으려는 것에 transient
	
	public Person() {}
	
	public Person(String name, String job) {
		this.name = name;
		this.job = job;
	}
	
	public String toString() {
		return name + "," + job;
	}
}

public class SerializationTest {

	public static void main(String[] args) {
		
		Person personRico = new Person("리코", "아이돌");
		Person personMari = new Person("마리", "이사장");
		
		// "Serial.txt"에 작성
		try(FileOutputStream fos = new FileOutputStream("Serial.txt");
				ObjectOutputStream oos = new ObjectOutputStream(fos)) {
			
			oos.writeObject(personRico);
			oos.writeObject(personMari);
			
		} catch (IOException e) {
			
			System.out.println(e);
			
		}
		
		// "Serial.txt" 를 복원
		try(FileInputStream fis = new FileInputStream("Serial.txt");
				ObjectInputStream ois = new ObjectInputStream(fis)) {
			
			Person pRico = (Person)ois.readObject();
			Person pMari = (Person)ois.readObject();
			
			System.out.println(pRico);
			System.out.println(pMari);
						
		} catch (IOException e) {
			
			System.out.println(e);
			
		} catch (ClassNotFoundException e) {
			
			System.out.println(e);
		}

	}

}

(3) Externalization 인터페이스

  • writerExternal(), readExternal() 메소드 구현 필요
  • 프로그래머가 직접 객체를 읽고 쓰는 코드를 구현
class Person implements Externalizable{
	
	String name;
	String job;
	
	public Person() {}

	public Person(String name, String job) {
		this.name = name;
		this.job = job;
	}
	
	public String toString()
	{
		return name + "," + job;
	}

	@Override
	public void writeExternal(ObjectOutput out) throws IOException {
		out.writeUTF(name);
		//out.writeUTF(job);
	}

	@Override
	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
		name = in.readUTF();
		//job = in.readUTF();
	}
	
}

2. RandomAccessFile 클래스

  • 입출력 클래스 중 유일하게 파일에 대합 입력과 출력을 동시에 할 수 있음
  • 파일 포인터가 있어 읽고 쓰는 위치의 이동이 가능함
public class RandomAccessFileTest {

	public static void main(String[] args) throws IOException {
		
		
		RandomAccessFile rf = new RandomAccessFile("random.txt", "rw"); // write, read가 동시에 가능
		
		rf.writeInt(100);
		System.out.println("pos:" + rf.getFilePointer());
		rf.writeDouble(3.14);
		System.out.println("pos:" + rf.getFilePointer());
		rf.writeUTF("헬로");
		System.out.println("pos:" + rf.getFilePointer());
		
		rf.seek(0); // rf를 맨 처음으로 이동시킴
		
		int i = rf.readInt();
		double d = rf.readDouble();
		String str = rf.readUTF();
		
		System.out.println(i);
		System.out.println(d);
		System.out.println(str);
		

	}

}

3. 데코레이터 패턴

(1) 데코레이터 패턴의 정의

  • 자바의 입출력 스트림은 데코레이터 패턴
  • 상속 보다 유연한 구현 방식 (지속적인 기능의 추가와 제거가 용이)
  • Component와 Decorator
    • Component : 실제 Object이며 입출력 스트림으로 따지면 기반 스트림
    • Decorator : Component나 다른 Decorator를 감싸며 부가 기능 / 행동을 추가. 스트림으로 따지면 보조 스트림

(2) 예제

  • 커피를 컴포넌트, 우유, 모카시럽, 휘핑 크림을 데코레이터로 했을 때 커피에 계속해서 재료를 얹어보기
  • [Coffee.java]
public abstract class Coffee { // 상속을 위한 추상화 클래스
	
	// component
	
	public abstract void brewing(); 

}
  • [EtiopiaAmericano.java]
public class EtiopiaAmericano extends Coffee {

	// ConcereteComponent
	
	@Override
	public void brewing() {
		System.out.print("Etiopia Americano ");
		
	}

}
  • [Decorator.java]
public abstract class Decorator extends Coffee { // 다른 클래스 상속을 위해 추상화
	
	Coffee coffee; // component를 포함해야 함
	
	public Decorator(Coffee coffee) {
		
		this.coffee = coffee;
		
	}
	
	@Override
	public void brewing() {
		
		coffee.brewing(); // component가 실행할 부분
		
	}
	
}
  • [Latte.java]
public class Latte extends Decorator {

	public Latte(Coffee coffee) {
		super(coffee); // 상위 클래스에 기본 생성자가 없어 super 필요
	}

	@Override
	public void brewing() {
		super.brewing();
		System.out.print("우유를 탄다 ");
	}
	
}
  • [Mocha.java]
public class Mocha extends Decorator {

	public Mocha(Coffee coffee) {
		super(coffee);
	}

	@Override
	public void brewing() {
		super.brewing();
		System.out.print("시럽을 탄다 ");
	}
	
}
  • [WhippingCream.java]
public class WhippingCream extends Decorator {

	public WhippingCream(Coffee coffee) {
		super(coffee);
	}

	@Override
	public void brewing() {
		super.brewing();
		System.out.print("휘핑 크림을 얹는다 ");
	}

}
  • [CoffeeTest.java]
public class CoffeeTest {

	public static void main(String[] args) {

		Coffee etiopiaCoffee = new EtiopiaAmericano();
		etiopiaCoffee.brewing();
		
		System.out.println();
		Coffee etiopiaLatte = new Latte(etiopiaCoffee);
		etiopiaLatte.brewing();
		
		System.out.println();
		Coffee mochaEtiopia = new Mocha(new Latte(etiopiaCoffee));
		mochaEtiopia.brewing();
		
		System.out.println();
		Coffee creamMochaEtiopia = new WhippingCream(new Mocha(new Latte(etiopiaCoffee)));
		creamMochaEtiopia.brewing();	
		
	}

}

profile
공부했던 내용들을 모아둔 창고입니다.

0개의 댓글