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

디자인 패턴 Composite 패턴

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

 

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

 

http://blog.naver.com/newsdu/80115957298

 

 

Entry 클래스

package kch;

/**

* @author kch

*/

public abstract class Entry {

       

        /**

         *@uml.property name="name"

         */

        public abstract String getName();

        public abstract int getSize();

        publicEntry add(Entry entry) throws FileTreatmentException{

              

               throw new FileTreatmentException();

              

        }

       

        public void printList(){

              

               printList("");

              

        }

       

        protected abstract void printList(String prefix);

        //prefix 앞에 붙여서 종류를 표시한다.

       

        publicString toString(){//문자열 표현

              

               returngetName() + " (" + getSize() + ")";

              

        }

}

FileTreatmentException 클래스

package kch;

public class FileTreatmentException extends RuntimeException {

       

        //File클래스에서 add 잘못 호출하게되면 예외가 발생하게 된다.

        publicFileTreatmentException(){

              

        }

        publicFileTreatmentException(String msg){

               super(msg);

        }

}

File 클래스

package kch;

public class File extendsEntry{

        /**

         *@uml.property name="name"

         */

        privateString name;

        /**

         *@uml.property name="size"

         */

        private int size;

        publicFile(String name, int size){

               this.name = name;

               this.size = size;

        }

       

        /**

         *@return

         *@uml.property name="name"

         */

        @Override

        publicString getName() {

               // TODO Auto-generated method stub

               returnname;

        }

        /**

         *@return

         *@uml.property name="size"

         */

        @Override

        public int getSize() {

               // TODO Auto-generated method stub

               returnsize;

        }

        protected void printList(String prefix) {

               // TODO Auto-generated method stub

              

               //prefix ""으로 들어오니까 아무것도 안들어옴

               //this.toString size 출력하라는 의미임.

               System.out.println(prefix + "/" + this.toString());

              

       

        }

       

}

Directory 클래스

package kch;

import java.util.ArrayList;

import java.util.Iterator;

public class Directory extendsEntry{

        /**

         *@uml.property name="name"

         */

        privateString name;

        /**

         *@uml.property name="directory"

         *@uml.associationEnd multiplicity="(0 -1)" elementType="kch.Entry"

         */

        private ArrayListdirectory = new ArrayList();

       

        publicDirectory(String name){

               this.name = name;

        }

       

        /**

         *@return

         *@uml.property name="name"

         */

        @Override

        publicString getName() {

               // TODO Auto-generated method stub

               return name;

        }

        @Override

        public int getSize() {

               // TODO Auto-generated method stub

               int size = 0;

               Iterator it = directory.iterator();

               while(it.hasNext()){

                       Entry entry = (Entry)it.next();

                      

                       //사이즈 구하는 부분이 핵심 부분.

                       //entry 인스턴스가 Directory Directory클래스의 getSize가 호출되고

                       //File 이면 File 클래스의 getSize가 호출된다

                       size += entry.getSize();

               }

              

               returnsize;

        }

        publicEntry add(Entry entry){

               directory.add(entry); //배열 리스트에 추가

               //entry Directory File이건 무조건 추가됨.

               //Directory size 없을 것이고 File이면 size 있을 것임.

               return this;

        }

       

        protected void printList(String prefix) {

               // TODO Auto-generated method stub

              

               //이부분에서 getSize가 호출된다.

               //toString안에 getSize함수가 호출되므로.

              

               System.out.println(prefix + "/" + this.toString());

              

               Iterator it = directory.iterator();

               //반복자를 이용해서 hasNextfalse일때까지 실행한다.

               //이부분에서 인스턴스가 Directory File이냐에 따라

               //printList함수가 다른것이 불려진다.

               //Directory 재귀적으로 된다.

               while(it.hasNext()){

                       Entry entry = (Entry)it.next();

                      

                       //prefix ""으로 들어오니까 아무것도 안들어옴

                       //Directory File과는 다르게 this.toString()이 없음

                       //이유는 사이즈가 없으니까

                       entry.printList(prefix + "/" + name);

               }

        }

}

Main 클래스

package kch;

public class Main {

        public static void main(String[] args){

               try{

                       System.out.println("Making root entries...");

                       Directory rootdir = new Directory("root");

                       Directory bindir = new Directory("bin");

                       Directory tempdir = new Directory("temp");

                       Directory usrdir = new Directory("usr");

                      

                       rootdir.add(bindir);//배열 리스트에 추가

                       rootdir.add(tempdir);//배열 리스트에 추가

                       rootdir.add(usrdir);//배열 리스트에 추가

                       bindir.add(new File("vi", 10000));

                       bindir.add(new File("latex", 20000));

                       rootdir.printList();

                      

                       System.out.println("");

                       System.out.println("Making user entries...");

                       Directory Kim = new Directory("Kim");

                       Directory Lee = new Directory("Lee");

                       Directory Park = new Directory("Park");

                       usrdir.add(Kim);

                       usrdir.add(Lee);

                       usrdir.add(Park);

                       Kim.add(new File("diary.html", 100));

                       Kim.add(new File("Composite.java", 200));

                       Lee.add(new File("memo.tex", 300));

                       Park.add(new File("game.doc", 400));

                       Park.add(new File("junk.mail", 500));

                       rootdir.printList();

               }catch(FileTreatmentException e){

                       e.printStackTrace();

               }

        }

       

}

 

 

Entry 클래스에서는 add를 예외가 발생하게 했는데

Directory클래스에서 오버라이드해서 의미를 바꿨습니다. 하지만 File클래스에서는Entry

add를 그대로 가져다가 쓰게됩니다.

다른 방법으로는

Directory 클래스에서만 add 메소드를 넣고 Entry File에는 안넣는 방법이 있는데 이부분

add를 사용할때 무조건 Directory 클래스로 형변환을 해야하는 단점이 있습니다.

 

 

반응형