Autumn SALE
데코레이터

자바로 작성된 데코레이터

데코레이터는 구조 패턴이며 새로운 행동들을 특수 래퍼 객체들 내에 넣어서 이러한 행동들을 객체들에 동적으로 추가할 수 있도록 합니다.

데코레이터를 사용하여 객체들을 제한 없이 래핑할 수 있습니다. 왜냐하면 대상 객체들과 데코레이터들은 같은 인터페이스를 따르기 때문입니다. 결과 객체는 모든 래퍼의 스태킹된 행동을 가질 것입니다.

복잡도:

인기도:

사용 예시들: 데코레이터는 자바 코드, 특히 스트림과 관련된 코드에서 꽤 표준적입니다.

다음은 코어 자바 라이브러리로부터 가져온 데코레이터의 몇 가지 예시들입니다:

식별: 데코레이터는 같은 클래스의 객체 또는 인터페이스를 현재 클래스로 수락하는 생성 메서드들 또는 생성자들로 인식할 수 있습니다.

인코딩 및 압축 데코레이터들

이 예시는 코드를 변경하지 않고 객체의 행동을 조정하는 방법을 보여줍니다.

처음에 비즈니스 로직 클래스는 일반 텍스트로만 데이터를 읽고 쓸 수 있었으나 그다음 표준 작업을 래핑 된 객체 내에 실행 후 새로운 행동을 추가하는 몇 개의 작은 래퍼 클래스들을 만들었습니다.

첫 번째 래퍼는 데이터를 암호화 및 해독하고 두 번째 래퍼는 데이터를 압축 및 추출합니다.

또 한 데코레이터를 다른 데코레이터로 래핑하여 이러한 래퍼들을 결합할 수도 있습니다.

decorators

decorators/DataSource.java: 읽기 및 쓰기 작업을 정의하는 공통 데이터 인터페이스

package refactoring_guru.decorator.example.decorators; public interface DataSource { void writeData(String data); String readData(); } 

decorators/FileDataSource.java: 간단한 데이터 판독기-작성기

package refactoring_guru.decorator.example.decorators; import java.io.*; public class FileDataSource implements DataSource { private String name; public FileDataSource(String name) { this.name = name; } @Override public void writeData(String data) { File file = new File(name); try (OutputStream fos = new FileOutputStream(file)) { fos.write(data.getBytes(), 0, data.length()); } catch (IOException ex) { System.out.println(ex.getMessage()); } } @Override public String readData() { char[] buffer = null; File file = new File(name); try (FileReader reader = new FileReader(file)) { buffer = new char[(int) file.length()]; reader.read(buffer); } catch (IOException ex) { System.out.println(ex.getMessage()); } return new String(buffer); } } 

decorators/DataSourceDecorator.java: 추상 기초 데코레이터

package refactoring_guru.decorator.example.decorators; public abstract class DataSourceDecorator implements DataSource { private DataSource wrappee; DataSourceDecorator(DataSource source) { this.wrappee = source; } @Override public void writeData(String data) { wrappee.writeData(data); } @Override public String readData() { return wrappee.readData(); } } 

decorators/EncryptionDecorator.java: 암호화 데코레이터

package refactoring_guru.decorator.example.decorators; import java.util.Base64; public class EncryptionDecorator extends DataSourceDecorator { public EncryptionDecorator(DataSource source) { super(source); } @Override public void writeData(String data) { super.writeData(encode(data)); } @Override public String readData() { return decode(super.readData()); } private String encode(String data) { byte[] result = data.getBytes(); for (int i = 0; i < result.length; i++) { result[i] += (byte) 1; } return Base64.getEncoder().encodeToString(result); } private String decode(String data) { byte[] result = Base64.getDecoder().decode(data); for (int i = 0; i < result.length; i++) { result[i] -= (byte) 1; } return new String(result); } } 

decorators/CompressionDecorator.java: 압축 데코레이터

package refactoring_guru.decorator.example.decorators; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Base64; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; public class CompressionDecorator extends DataSourceDecorator { private int compLevel = 6; public CompressionDecorator(DataSource source) { super(source); } public int getCompressionLevel() { return compLevel; } public void setCompressionLevel(int value) { compLevel = value; } @Override public void writeData(String data) { super.writeData(compress(data)); } @Override public String readData() { return decompress(super.readData()); } private String compress(String stringData) { byte[] data = stringData.getBytes(); try { ByteArrayOutputStream bout = new ByteArrayOutputStream(512); DeflaterOutputStream dos = new DeflaterOutputStream(bout, new Deflater(compLevel)); dos.write(data); dos.close(); bout.close(); return Base64.getEncoder().encodeToString(bout.toByteArray()); } catch (IOException ex) { return null; } } private String decompress(String stringData) { byte[] data = Base64.getDecoder().decode(stringData); try { InputStream in = new ByteArrayInputStream(data); InflaterInputStream iin = new InflaterInputStream(in); ByteArrayOutputStream bout = new ByteArrayOutputStream(512); int b; while ((b = iin.read()) != -1) { bout.write(b); } in.close(); iin.close(); bout.close(); return new String(bout.toByteArray()); } catch (IOException ex) { return null; } } } 

Demo.java: 클라이언트 코드

package refactoring_guru.decorator.example; import refactoring_guru.decorator.example.decorators.*; public class Demo { public static void main(String[] args) { String salaryRecords = "Name,Salary\nJohn Smith,100000\nSteven Jobs,912000"; DataSourceDecorator encoded = new CompressionDecorator( new EncryptionDecorator( new FileDataSource("out/OutputDemo.txt"))); encoded.writeData(salaryRecords); DataSource plain = new FileDataSource("out/OutputDemo.txt"); System.out.println("- Input ----------------"); System.out.println(salaryRecords); System.out.println("- Encoded --------------"); System.out.println(plain.readData()); System.out.println("- Decoded --------------"); System.out.println(encoded.readData()); } } 

OutputDemo.txt: 실행 결과

- Input ---------------- Name,Salary John Smith,100000 Steven Jobs,912000 - Encoded -------------- Zkt7e1Q5eU8yUm1Qe0ZsdHJ2VXp6dDBKVnhrUHtUe0sxRUYxQkJIdjVLTVZ0dVI5Q2IwOXFISmVUMU5rcENCQmdxRlByaD4+ - Decoded -------------- Name,Salary John Smith,100000 Steven Jobs,912000 

다른 언어로 작성된 데코레이터

C#으로 작성된 데코레이터 C++로 작성된 데코레이터 Go로 작성된 데코레이터 PHP로 작성된 데코레이터 파이썬으로 작성된 데코레이터 루비로 작성된 데코레이터 러스트로 작성된 데코레이터 스위프트로 작성된 데코레이터 타입스크립트로 작성된 데코레이터