public interface Beverage {
String getDescription();
double cost();
}
public class Espresso implements Beverage {
@Override
public String getDescription() {
return "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
public abstract class BeverageDecorator implements Beverage {
protected Beverage beverage;
public BeverageDecorator(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription();
}
}
Decorator 클래스를 확장하여 추가적인 기능을 제공; 이 클래스는 동적으로 기능을 추가할 때 사용
public class Milk extends BeverageDecorator {
public Milk(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Milk";
}
@Override
public double cost() {
return beverage.cost() + 0.50;
}
}
기본 객체 생성: ConcreteComponent 객체를 생성합니다. 이 객체는 기본적인 기능을 가지고 있습니다.
데코레이터 적용: ConcreteDecoratorA와 ConcreteDecoratorB를 순차적으로 적용하여 기능을 확장합니다. 각 데코레이터는 Component 객체를 인수로 받아 기능을 확장
재할당(다형적 참조)을 통한 확장된 객체 사용: 확장된 객체를 사용하여 결과를 출력합니다. 각 데코레이터는 이전의 상태를 기반으로 추가 기능을 제공하므로, 결과적으로 객체의 기능이 단계적으로 확장
public class CoffeeShop {
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
beverage = new Milk(beverage);
System.out.println(beverage.getDescription() + " $" + beverage.cost());
beverage = new Mocha(beverage);
System.out.println(beverage.getDescription() + " $" + beverage.cost());
}
}

import java.io.*;
public class InputStreamDecoratorExample {
public static void main(String[] args) {
String filePath = "example.txt";
try {
// FileInputStream을 생성합니다.
InputStream fileInputStream = new FileInputStream(filePath);
// FileInputStream을 BufferedInputStream으로 데코레이팅합니다.
InputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
// BufferedInputStream을 LineNumberInputStream으로 데코레이팅합니다.
LineNumberInputStream lineNumberInputStream = new LineNumberInputStream(bufferedInputStream);
// 파일을 읽고 출력합니다.
int data;
while ((data = lineNumberInputStream.read()) != -1) {
System.out.print((char) data);
// 줄바꿈 문자일 때 줄 번호를 출력합니다.
if (data == '\n') {
System.out.println("Line number: " + lineNumberInputStream.getLineNumber());
}
}
// 스트림을 닫습니다.
lineNumberInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}