처음에는 아래 링크에 들어가셔서 한번 읽어보시면 이 패턴을 이해하는데 아주 도움이 될 것 입니다.
http://blog.naver.com/newsdu/80115957298
Display 클래스
package kch;
public abstract class Display {
public abstract int getColumns();//가로 문자수를 얻는다.
public abstract int getRows();//세로 행수를 얻는다.
public abstract String getRowText(introw);//row번째의 문자열을 얻는다.
public final void show(){//전부 표시한다.
for(int i=0 ; i < getRows() ; i++){
System.out.println(getRowText(i));
}
}
}
StringDisplay 클래스
package kch;
public class StringDisplay extendsDisplay{
//생일케이크의 기본이 되는 스폰지케이크 부분.
/**
*@uml.property name="string"
*/
privateString string;
publicStringDisplay(String string){
this.string = string;
}
public int getColumns() {//문자수 반환
// TODO Auto-generated method stub
return string.getBytes().length;
}
public int getRows() {//행은 1
// TODO Auto-generated method stub
return 1;
}
publicString getRowText(int row) {//row가 0이면 반환
// TODO Auto-generated method stub
if(row== 0){
return string;
}else{
return null;
}
}
}
Border 클래스
package kch;
public abstract class Border extendsDisplay{
/**
*@uml.property name="display"
*@uml.associationEnd multiplicity="(1 1)"
*/
protectedDisplay display;//
protectedBorder(Display display){
this.display = display;
}
}
SideBorder
package kch;
public class SideBorder extendsBorder{
/**
*@uml.property name="borderChar"
*/
private char borderChar;
publicSideBorder(Display display, char ch) {
super(display);
// TODO Auto-generated constructor stub
this.borderChar = ch;
}
@Override
public int getColumns() {//문자수는 내용물의 양쪽에 장식 문자수를 고려해야됨
//|hello| 여기서 |갯수를 고려해줘야되서 2를 더해야됨.
// TODO Auto-generated method stub
return 1 + display.getColumns() + 1;
}
@Override
public int getRows() {
// TODO Auto-generated method stub
return display.getRows();
}
@Override
publicString getRowText(int row) {
// TODO Auto-generated method stub
return borderChar + display.getRowText(row) + borderChar;//옆에 장식을추가함.
}
}
FullBorder 클래스
package kch;
public class FullBorder extendsBorder{
publicFullBorder(Display display){
super(display);
}
// @Override
public int getColumns() {
//+++++++
//+hello+
//+++++++ 이런식이여서 columns를 추가 시켜줘야됨.
// TODO Auto-generated method stub
//display는 Border 클래스에서상속 받음.
return 1 + display.getColumns() + 1;
}
// @Override
public int getRows() {
//+++++++
//+hello+
//+++++++ 이런식이여서 row를 추가 시켜줘야됨.
// TODO Auto-generated method stub
return 1 + display.getRows() + 1;
}
// @Override
publicString getRowText(int row) {
// TODO Auto-generated method stub
if(row== 0){
return "+" + makeLine('-', display.getColumns()) + "+";
}else if(row == display.getRows() + 1){
return "+" + makeLine('-', display.getColumns()) + "+";
}else{
return "|" + display.getRowText(row-1) + "|";
}
}
privateString makeLine(char ch, int count){
StringBuffer buf = new StringBuffer();
for(int i = 0; i < count; i++){
buf.append(ch);
}
returnbuf.toString();
}
}
package kch;
public class Main {
public static void main(String [] args){
Display b1 = new StringDisplay("Helloworld.");
Display b2 = new SideBorder(b1, '#');
//b2의 이러한 선언에 의해서 Border에 있는 Display display의인스턴스가
//StringDisplay클래스로된다.
Display b3 = new FullBorder(b2);
System.out.println("b1출력.");
b1.show();
System.out.println("b2출력.");
//public final void show(){//전부 표시한다.
//
//for(int i=0 ; i < getRows() ; i++){
// System.out.println(getRowText(i));
//}
//for 루프에서 display.getRows(StringDisplay클래스)로 1이 반환된다.
//이유는 display는 위에서 말한 것처럼 StringDisplay 인스턴스를가지고 있기때문에...
//i=0일 때
//public String getRowText(int row) {
// returnborderChar + display.getRowText(row) + borderChar;//옆에 장식을 추가함.
//}
//display.getRowText(0)이어서 StringDisplay 의 getRowText에 의해서 string 값이 반환되고
//borderChar + display.getRowText(row) + borderChar 로 옆에 #이 붙여져서 출력된다.
b2.show();
System.out.println("b3출력.");
b3.show();
//public final void show(){//전부 표시한다.
//
//for(int i=0 ; i < getRows() ; i++){
// System.out.println(getRowText(i));
//}
//for루프에서 처음에 getRows를 부르게된다. 이때는 FullBorder인스턴스이므로
//FullBorder의 getRows가 호출된다.
//public int getRows() {
//+++++++
//+hello+
//+++++++ 이런식이여서 row를 추가 시켜줘야됨.
// return 1 +display.getRows() + 1;
//}
//여기서 display.getRows()를 호출하게되는대 이때는
//Display b3 = new FullBorder(b2); 에 의해서 display인스턴스가 SideBorder이므로 여기로 간다.
//SideBorder의 getRows로 가게되고
//public int getRows() {
// returndisplay.getRows();
//}
//여기서의 display의 인스턴스는 처음에 선언했던대로 StringDisplay이다.
//이런식으로 안쪽으로 파고드는재귀적 구성이다.
//그래서 return 값은 1이 되고
//return 1 + display.getRows() + 1;에 의해서 최종 for루프의 리턴값은 3이 된다.
//나머지도 생각해보면 이런식으로된다.
Display b4 =
new SideBorder(
new FullBorder(
new FullBorder(
new SideBorder(
newFullBorder(
newStringDisplay("안녕하세요.")
),
'*'//SideBorder를 위한 것.
)
)
),
'/'
);
System.out.println("b4출력.");
b4.show();
//응용 버젼 이런식으로 런타임때계속 장식을 추가할 수 있다.
}
}
Decorator 패턴은 메인에서 기능을 계속 추가할 수 있다는 점이장점입니다. 물론 기능을 추가하기위해서 기존의 클래스를 변경하지 않아도 됩니다.
java.io 패키지에도
Reader reader = new BufferedReader(newFileReader(“datafile.txt”)); 가 있는데
이것이 바로 Decorator 패턴을 이용한 것 입니다.
객체의 내부가 아닌 외부적인 기능의 추가는 이 Decorator패턴이유용하고 내부적인 기능의 추가는 Strategy 패턴이 유용합니다.
'프로그래밍 > 자바 디자인패턴' 카테고리의 다른 글
디자인 패턴 위임에 의한 Adapter 패턴(인스턴스를 이용한) (0) | 2012.08.03 |
---|---|
디자인 패턴 Adapter패턴 상속을 사용한 Adapter패턴 (0) | 2012.08.03 |
디자인패턴 Chain of Responsibility 패턴 (0) | 2012.08.02 |
디자인 패턴 Visitor 패턴 (0) | 2012.08.01 |
디자인 패턴 Composite 패턴 (0) | 2012.08.01 |
디자인 패턴 Strategy 패턴 (0) | 2012.08.01 |
디자인 패턴 Bridge 패턴 (0) | 2012.08.01 |
디자인 패턴 Builder 패턴 (1) | 2012.08.01 |