프로그래밍/자바 디자인패턴

디자인 패턴 Decorator 패턴

가카리 2012. 8. 1. 22:16
반응형

 

 

처음에는 아래 링크에 들어가셔서 한번 읽어보시면 이 패턴을 이해하는데 아주 도움이 될 것 입니다.

 

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 패턴이 유용합니다.

 

 

반응형