공적's life

3-2 클래스로 분리 본문

Programing/Java programing

3-2 클래스로 분리

melpis 2010. 7. 25. 19:35

우리는 이제 클래스로 분리 하려고 합니다. 저번에는 메소드로 분리하였는데

 

어느 정도 분업이 가능했지만 이제는 좀더 진화한 분업을 위하여 클래스로

 

분리하여 각자 클래스를 작성할 수 있게 해보겠습니다.

 

일단 기능 별로 분리 해보도록 하죠^^;

 

제가 제일 처음 한일은 먼저 패키지를 작성하였습니다. 이제는 패키지로 관리 해볼까 해서요^^;

 

일단 우리가 작성하는 패키지의 이름은 com.tistory.melpis.board 입니다. 어디서 많이 보던

 

이름이죠? 일반적으로 패키지는 주소를 꺼꾸로 잡습니다. 간단하죠? 만약에 꺼꾸로 하지 않으면

 

묶이질 않고 서로 따로 놀게 됩니다.

 

그 다음에 한일은 Board의 클래스 이름을 변경 하였습니다. 일단은 BoardExecution 라고 했네요,

 

그리고 메소드들을 전부 BoardManager클래스를 생성하여 옴 겼습니다.

 

일단 컴파일 에러 하나씩 잡아볼까요?

 

그전에 다른, 클래스에서 참조 할 수 있도록 private static을 제거해보죠.

 

제거하고 나서

 

    //3.3 클래스 생성

    BoardManager boardManager = new BoardManager();

            

    if (userAction.equals("RF")) {

            boardManager.registDoumentForm();

        } else if (userAction.equals("RD")) {

            boardManager.registDocument(outputData);

        } else if (userAction.equals("VD")) {

            boardManager.viewDocument(outputData);

        } else if (userAction.equals("VL")) {

            boardManager.viewDocumentList();

        } else if (userAction.equals("DD")) {

            boardManager.deleteDocument(outputData );

        } else if (userAction.equals("EF")) {

            boardManager.editDocumentForm(outputData);

        } else if (userAction.equals("ED")) {

            boardManager.editDocument(outputData);

        } else {

            System.out.println("잘못 입력하셨습니다");

        }

}

 

이렇게 바꾸니까 BoardExecution 란 클래스에 컴파일에러는 전부 제거 되었네요.

 

자아 이제 BoardManger클래스에 컴파일에러를 잡아 볼까요?

 

BoardExecution 에 있던 property를 옴 기니까 그냥 해결되네요^^;

 

아 쉽네요.

 

그리고 BoardManger 생성 할 때는 while문 밖에서 생성해야 합니다. 안 그러면 돌 때 마다 생성해서

 

데이터가 리셋이 되요.

 

음 그 다음에는 깔끔하지 못한 BoardManager를 손볼 시간입니다.

 

static영역을 사용하는 것은 안전하지 못하기 때문에

 

static대신 다른 것을 해보도록 하고, 이제는 데이터를 좀더 체계적으로 관리하기 위해서

 

단순히 타입으로 저장하는 것이 아니라 이것도 클래스로 옴 겨서 따로 관리해보도록 하죠.

 

그리고 기존에 SEQ번호를 루프를 통해서 검색했지만 색인을 만들어서 빠르게 검색해보도록 하죠.

 

잠깐 진행된 사항을 살펴볼까요?

 

public class BoardDataBase {

    private static int systemSeq = 0;

    private List<Map<String, String>> tableData = null;

    

    public BoardDataBase() {

        this.tableData = new ArrayList<Map<String,String>>();

    }

    

    public static int getSystemSeq(){

        systemSeq+=1;

        return systemSeq;

    }

    

    public void setTableData(Map<String,String> tableData){

        this.tableData.add(tableData);

    }

    

    public List<Map<String,String>> getTableData(){

        return this.tableData;

    }

    

}

이제 생성자라는 것을 사용하게 되네요. 무언가 초기화 시켜줄 일이 있으면 사용한다고

 

생각하시면 됩니다. 여기서 한가지 알아야 할 점은 객체를 사용할 때 생성해주는 것이 좋아요.

 

일단은 선언만 해놓고 나중에 객체 생성하는 거죠. 하지만 세상에 반드시 라는 말은 잘 존재 하지 않기

 

때문에 여기에도 꼭 늦게 생성해줘야 하는 것은 아닙니다. 예외는 나중에 알아 보도록 하고요.

 

이 클래스는 어떻게 추출됐는가 하면요. 데이터를 다루는 것을 단지 이쪽으로 옴 긴 것뿐입니다.

 

자아 다시 진행해볼까요?

 

public class BoardManager {

    private BoardDataBase boardDataBase = null;

    

    public BoardManager(){

        this.boardDataBase = new BoardDataBase();

    }

    public void registDocument(String[] outputData) {

        // 6. 문서 번호 가져오기

        int systemSeq = BoardDataBase.getSystemSeq();

 

        this.boardDataBase.setTableData(documentSave);

}

}

 

코드에 일부분만 발취했습니다. 모든 메소드에서 BoardDataBase를 사용하기 때문에

 

Property로 이동되었고, SystemSeq는 단순히 번호만 주기 때문에 static으로 작성하였습니다.

 

이렇게 단순하게 사용 할 때는 static을 사용하시면 됩니다.

 

하지만 여기서 끝난 것이 아닙니다. 아직도 BoardManage클래스에서 데이터를 다루는 부분이 있네요.

 

이것들을 다시 BoardDataBase로 옴 겨 보도록 하죠^^;

 

public class BoardManager {

    private BoardDataBase boardDataBase = null;

    

    public BoardManager(){

        this.boardDataBase = new BoardDataBase();

    }

    

    // 문서 등록 폼

    public void registDoumentForm() {

 

        // 1. 등록 폼출력

        System.out.println("제목: ");

        System.out.println("내용: ");

 

    }

    // 문서 등록

    public void registDocument(String[] outputData) {

        // 1.1 제목 추출

        String userInputTitle = outputData[1];

        // 1.2 내용 추출

        String userInputContent = outputData[2];

        // 2. 유효성 검사

        if (userInputTitle.length() < 1 && userInputTitle.length() > 600) {

            return;

        }

        if (userInputContent.length() < 1 && userInputContent.length() > 2000) {

            return;

        }

        // 3. 등록

        this.boardDataBase.insert(userInputTitle, userInputContent);

        // 4. 결과 출력

        System.out.println("등록 완료");

 

    }

    

    // 문서 상세 보기

    public void viewDocument(String[] outputData) throws ParseException {

        // 사용자가 입력한 문서 번호 가져오기

        String userInputSeq = outputData[1];

        int parameterSeq = Integer.parseInt(userInputSeq);

        

        // 일치할경우 저장할 Map타입

        Map<String, String> documentSave =this.boardDataBase.select(parameterSeq);

        

        if (documentSave != null) {

            

            String tempSeq = documentSave.get("SEQ");

            int seq = Integer.parseInt(tempSeq);

 

            String title = documentSave.get("TITLE");

            String content = documentSave.get("CONTENT");

 

            String tempRegistDate = documentSave.get("REGIST_DATE");

            SimpleDateFormat dateFormat = new SimpleDateFormat(

                    "yyyy.MM.dd HH:mm:ss", Locale.KOREA);

            Date registDate = dateFormat.parse(tempRegistDate);

 

            String tempHit = documentSave.get("HIT");

            int hit = Integer.parseInt(tempHit);

 

            System.out.println("글번호 : " + seq);

            System.out.println("제목 : " + title);

            System.out.println("등록일 : " + registDate);

            System.out.println("조회수 : " + hit);

            System.out.println("내용 : " + content);

        }

 

    }

      

 

    public void viewDocumentList()

            throws ParseException {

        

        //DataBase클래스에서 데이터 가져오기

        List<Map<String, String>> tableData = this.boardDataBase.selectList();

          

        

        for (int indexI = 0; indexI < tableData.size(); indexI++) {

            Map<String, String> documentSave = tableData.get(indexI);

 

            String tempSeq = documentSave.get("SEQ");

            int seq = Integer.parseInt(tempSeq);

 

            String title = documentSave.get("TITLE");

            String content = documentSave.get("CONTENT");

 

            String tempRegistDate = documentSave.get("REGIST_DATE");

            SimpleDateFormat dateFormat = new SimpleDateFormat(

                    "yyyy.MM.dd HH:mm:ss", Locale.KOREA);

            Date registDate = dateFormat.parse(tempRegistDate);

 

            String tempHit = documentSave.get("HIT");

            int hit = Integer.parseInt(tempHit);

 

            System.out.println("글번호 : " + seq);

            System.out.println("제목 : " + title);

            System.out.println("등록일 : " + registDate);

            System.out.println("조회수 : " + hit);

            System.out.println("내용 : " + content);

 

        }

 

    }

 

    public void deleteDocument(String[] outputData) {

        // 사용자가 입력한 문서 번호 가져오기

        String userInputSeq = outputData[1];

        

        int parameterSeq = Integer.parseInt(userInputSeq);

          

        

        this.boardDataBase.delete(parameterSeq);

        

 

        System.out.println("삭제 되었습니다");

 

    }

 

    public void editDocumentForm(String[] outputData) throws ParseException {

        // 사용자가 입력한 문서 번호 가져오기

        String userInputSeq = outputData[1];

 

        int parameterSeq = Integer.parseInt(userInputSeq);

        

        // 일치할경우 저장할 Map타입

        Map<String, String> documentSave = this.boardDataBase.select(parameterSeq);

        

        // null 경우 처리 하지 않음

        if (documentSave != null) {

 

            String tempSeq = documentSave.get("SEQ");

            int seq = Integer.parseInt(tempSeq);

 

            String title = documentSave.get("TITLE");

            String content = documentSave.get("CONTENT");

 

            String tempRegistDate = documentSave.get("REGIST_DATE");

            SimpleDateFormat dateFormat = new SimpleDateFormat(

                    "yyyy.MM.dd HH:mm:ss", Locale.KOREA);

            Date registDate = dateFormat.parse(tempRegistDate);

 

            String tempHit = documentSave.get("HIT");

            int hit = Integer.parseInt(tempHit);

 

            System.out.println("글번호 : " + seq);

            System.out.println("제목 : " + title);

            System.out.println("등록일 : " + registDate);

            System.out.println("조회수 : " + hit);

            System.out.println("내용 : " + content);

        }

 

    }

 

    public void editDocument(String[] outputData) {

        // 사용자가 입력한 문서 번호 가져오기

        String userInputSeq = outputData[1];

        String userInputTitle = outputData[2];

        String userInputContent = outputData[3];

        

        int parameterSeq = Integer.parseInt(userInputSeq);

        

        this.boardDataBase.update(parameterSeq,userInputTitle,userInputContent);

        

        System.out.println("수정완료 하였습니다");

 

      

 

    }

}

전보다 간단해진 BoardManager클래스입니다. 이 클래스는 데이터를 넘겨주거나 혹은 출력하거나

 

이 두 가지 일만 한답니다. 저 두 개도 분리 해내고 싶지만 여기까지 하겠습니다.

 

이제 BoardDataBase를 제대로 만들어 볼까요? 이전까지 완성된 BoardDatabase입니다.

 

public class BoardDataBase {

    private static int systemSeq = 0;

    private List<Map<String, String>> tableData = null;

 

    

    public BoardDataBase() {

        this.tableData = new ArrayList<Map<String,String>>();

    }

    

    private static int getSystemSeq(){

        systemSeq+=1;

        return systemSeq;

    }

      

 

    

    //등록 (insert)

    public void insert(String title, String content){

        

        // 1. 문서 번호 가져오기

        int systemSeq = BoardDataBase.getSystemSeq();

        // 2. 등록일 가져오기

        Date systemDate = new Date();

        SimpleDateFormat dateFormat = new SimpleDateFormat(

                "yyyy.MM.dd HH:mm:ss", Locale.KOREA);

        String sysDate = dateFormat.format(systemDate);

        // 3. 조회수 입력

        int configHit = 0;

        Map<String, String> saveData = new HashMap<String, String>();

        // 4. 등록

        saveData.put("SEQ", String.valueOf(systemSeq));

        saveData.put("TITLE", title);

        saveData.put("CONTENT", content);

        saveData.put("REGIST_DATE", sysDate);

        saveData.put("HIT", String.valueOf(configHit));

        this.tableData.add(saveData);

 

    }

      

        

    

    // 한건 조회 (select)

    public Map<String,String> select(int seq){

        

        //DataBase클래스에서 데이터 가져오기

        List<Map<String, String>> tableData = this.tableData;

        //String 타입으로 변환

        String userInputSeq = String.valueOf(seq);

        //return 해 줄 데이터

        Map<String,String> returnData= null;

        

        // 검사

        for (int indexI = 0; indexI < tableData.size(); indexI++) {

            Map<String, String> checkData = tableData.get(indexI);

            if (userInputSeq.equals(checkData.get("SEQ"))) {

                int updateHit = Integer.parseInt(checkData.get("HIT")) + 1;

                checkData.put("HIT", String.valueOf(updateHit));

                returnData = checkData;

                break;

            }

        }

        

        return returnData;

    }

    

    //여러건 조회 selectList

    

    public List<Map<String,String>> selectList(){

        return this.tableData;

    }

    

    //삭제 (delete)

    public void delete(int seq) {

 

        String userInputSeq = String.valueOf(seq);

        // 검사

        for (int indexI = 0; indexI < tableData.size(); indexI++) {

            Map<String, String> checkData = tableData.get(indexI);

            if (userInputSeq.equals(checkData.get("SEQ"))) {

                this.tableData.remove(indexI);

                break;

            }

        }

    }

    //수정 (update)

    public void update(int seq,String title,String content){

        // 일치할경우 저장할 Map타입

        Map<String, String> saveData = null;

 

        String userInputSeq = String.valueOf(seq);

        

        //DataBase클래스에서 데이터 가져오기

        List<Map<String, String>> tableData = this.tableData;

        // 검사

        for (int indexI = 0; indexI < tableData.size(); indexI++) {

            Map<String, String> checkData = tableData.get(indexI);

            if (userInputSeq.equals(checkData.get("SEQ"))) {

                checkData.put("TITLE", title);

                checkData.put("CONTENT", content);

                Date systemDate = new Date();

                SimpleDateFormat dateFormat = new SimpleDateFormat(

                        "yyyy.MM.dd HH:mm:ss", Locale.KOREA);

                String sysDate = dateFormat.format(systemDate);

                checkData.put("REGIST_DATE", sysDate);

                break;

            }

        }    

    }

      

    

}

뭐 실상 전에 BoardManager에서 하던 것을 이리로 옴 긴 것뿐입니다. 별거 없어요.

 

이제 색인을 만들어서 빠르게 찾거나 삭제 해보도록 할까요?

 

public class BoardDataBase {

    private static int systemSeq = 0;

    private List<Map<String, String>> tableData = null;

    private List<String> index = null;

 

    public BoardDataBase() {

        this.tableData = new ArrayList<Map<String,String>>();

        this.index = new ArrayList<String>();

    }

    

    private static int getSystemSeq(){

        systemSeq+=1;

        return systemSeq;

    }

    

    private void addIndex(int seq){

        this.index.add(String.valueOf(seq));

    }

    private void updateIndex(int seq){

        this.index.remove(String.valueOf(seq));

    }

    

    private int getIndex(int seq){

        int dataLoaction = this.index.indexOf(String.valueOf(seq));

        return dataLoaction;

    }

      

    

    //등록 (insert)

    public void insert(String title, String content){

        

        // 1. 문서 번호 가져오기

        int systemSeq = BoardDataBase.getSystemSeq();

        // 2. 등록일 가져오기

        Date systemDate = new Date();

        SimpleDateFormat dateFormat = new SimpleDateFormat(

                "yyyy.MM.dd HH:mm:ss", Locale.KOREA);

        String sysDate = dateFormat.format(systemDate);

        // 3. 조회수 입력

        int configHit = 0;

        Map<String, String> saveData = new HashMap<String, String>();

        // 4. 등록

        saveData.put("SEQ", String.valueOf(systemSeq));

        saveData.put("TITLE", title);

        saveData.put("CONTENT", content);

        saveData.put("REGIST_DATE", sysDate);

        saveData.put("HIT", String.valueOf(configHit));

        this.tableData.add(saveData);

        

        addIndex(systemSeq);

 

    }

      

        

    

    // 한건 조회 (select)

    public Map<String,String> select(int seq){

        //return 해 줄 데이터

        Map<String,String> returnData= null;

        // index에서 위치 찾아옴

        int dataLoacation = getIndex(seq);

        //table에서 데이터 꺼내옴

        returnData = this.tableData.get(dataLoacation);

        return returnData;

    }

    

    //여러건 조회 selectList

    

    public List<Map<String,String>> selectList(){

        return this.tableData;

    }

    

    //삭제 (delete)

    public void delete(int seq) {

        int dataLocation = getIndex(seq);

        this.tableData.remove(dataLocation);

        updateIndex(seq);

        

    }

    //수정 (update)

    public void update(int seq,String title,String content){

        // 일치할경우 저장할 Map타입

        Map<String, String> saveData = null;

 

        int dataLoaction = this.getIndex(seq);

        saveData = this.tableData.get(dataLoaction);

        

        saveData.put("TITLE", title);

        saveData.put("CONTENT", content);

        Date systemDate = new Date();

        SimpleDateFormat dateFormat = new SimpleDateFormat(

                        "yyyy.MM.dd HH:mm:ss", Locale.KOREA);

        String sysDate = dateFormat.format(systemDate);

        saveData.put("REGIST_DATE", sysDate);

    

    }

      

    

}

클래스가 색인(index) 하나로 간단해졌죠?

 

이제 잠깐 인덱스 이야기를 해야 할듯하네요. 현재 상태에서는 tableData와 index 의 줄 즉 사이즈는

 

동일합니다. 예를 들어서 보죠.

Seq

Title

위치

1

하이

0

2

안녕하세요

1

3

방가요

2

 

이런 식으로 tableData를 구성되어있습니다.

1

위치[0]

2

위치[1]

3

위치[2]

 

여기는 index입니다. Index는 List타입으로 seq를 저장합니다. 만약에 한 건의 데이터가

 

index에서 seq로 검색합니다. indexOf란 메소드를 사용해서 던져준 seq가 어떤 위치에 있는지

 

알아 냅니다. 그 다음은 그냥 tableData에서 꺼내 오기만 하면 끝입니다.

 

여기까지는 별로 문제가 안됩니다. 다음은 삭제 할 때를 살펴보죠.

 

Seq가 2인 것을 지워 봅니다.

Seq

Title

위치

1

하이

0

3

방가요

1

 

이렇게 됩니다. 이제 index도 고쳐볼까요?

1

위치[0]

3

위치[1]

 

이렇게 됩니다. tableData와 index가 항상 같은 사이즈를 유지 하는 것이 중요하고

 

같은 위치에 같은 seq를 가져야 합니다.

 

코드를 보면 사실 별거 없습니다. 생각만 조금하시면 금방 할 수 있어요.

 

자 오늘로써 java 버전 문서 관리를 끝내보고 I.O와 file을 해보도록하죠^^;


오늘은 코드량이 많아서 압축해서 올리게요. 스크롤 압박이 장난이 아닐거 같아서요 ^^;


'Programing > Java programing' 카테고리의 다른 글

4-1 I.O and File  (0) 2010.07.31
3-3 메소드, 클래스 분리 회고  (0) 2010.07.26
3-1 메소드로 분리  (0) 2010.07.24
2-6 다음 진행을 위한 회고  (0) 2010.07.23
2-5 문서관리 (수정)  (0) 2010.07.22