JAVA
[디자인패턴] Decorator 패턴
gom1n
2022. 4. 28. 08:59
Decorator 패턴?
중심이 되는 객체에, 장식과 같은 부가적인 기능을 하나씩 입혀서 목적에 어울리는 객체로 만들고자 생겨난 패턴이다.
Decorator 패턴의 객체들은 장식을 할 수 있는 동시에, 장식이 될 수 있는 가능성이 있다. (장식자이면서, 장식의 대상이 된다.)
언뜻 보면 Composite패턴과 비슷할 정도로 재귀적인 구조를 가진다.
그러나 객체가 다른 객체에 포함될 수 있는 Composite 패턴과 달리, Decorator 패턴은 객체는 다른 객체에 의해 덧붙여진다는, 즉 기능추가가 된다는 점에서 다르다.
다이어그램
Decorator 패턴의 핵심 클래스 : Border.class
public abstract class Border extends Display {
protected Display display;
protected Border(Display display) {
this.display = display;
}
}
Decorator Pattern in Java API
Java IO classes, like FileReader, BufferedReader, etc.
연습문제
12-1) 이 장의 프로그램에 추가하는 형태로 상하에 장식문자가 붙는 UpDownBorder 클래스를 만드십시오. UpDownBorder 클래스는 다음과 같이 사용한다고 가정합니다.
Main.class에서의 UpDownBorder 클래스 사용
public class Main {
public static void main(String[] args) {
Display b1 = new StringDisplay("Hello, world.");
Display b2 = new UpDownBorder(b1, '-');
Display b3 = new SideBorder(b2, '*');
b1.show();
b2.show();
b3.show();
Display b4 =
new FullBorder(
new UpDownBorder(
new SideBorder(
new UpDownBorder(
new SideBorder(
new StringDisplay("안녕하세요."),
'*'
),
'='
),
'|'
),
'/'
)
);
b4.show();
}
}
답) UpDownBorder 클래스
public class UpDownBorder extends Border {
private char borderChar;
public UpDownBorder(Display display, char ch) {
super(display);
this.borderChar = ch;
}
public int getColumns() {
return display.getColumns();
}
public int getRows() {
return 1 + display.getRows() + 1;
}
public String getRowText(int row) {
if (row == 0 || row == getRows() - 1) {
return makeLine(borderChar, getColumns());
} else {
return display.getRowText(row - 1);
}
}
private String makeLine(char ch, int count) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < count; i++) {
buf.append(ch);
}
return buf.toString();
}
}
12-2) ConcreteComponent 역할로 복수의 문자열을 표시하는 MultiStringDisplay 클래스를 만드십시오. MultiStringDisplay는 다음과 같이 사용한다고 가정합니다.
Main.class에서의 MultiStringDisplay 클래스 사용
public class Main {
public static void main(String[] args) {
MultiStringDisplay md = new MultiStringDisplay();
md.add("좋은 아침입니다.");
md.add("안녕하세요.");
md.add("안녕히 주무세요. 내일 만나요.");
md.show();
Display d1 = new SideBorder(md, '#');
d1.show();
Display d2 = new FullBorder(md);
d2.show();
}
}
답) MultiStringDisplay 클래스
import java.util.ArrayList;
public class MultiStringDisplay extends Display {
private ArrayList body = new ArrayList();
private int columns = 0;
public void add(String msg) {
body.add(msg);
updateColumn(msg);
}
public int getColumns() {
return columns;
}
public int getRows() {
return body.size();
}
public String getRowText(int row) {
return (String)body.get(row);
}
private void updateColumn(String msg) {
if (msg.getBytes().length > columns) {
columns = msg.getBytes().length;
}
for (int row = 0; row < body.size(); row++) {
int fills = columns - ((String)body.get(row)).getBytes().length;
if (fills > 0) {
body.set(row, body.get(row) + spaces(fills));
}
}
}
private String spaces(int count) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < count; i++) {
buf.append(' ');
}
return buf.toString();
}
}