잡동사니에도 사랑을

[21.08.27] Interface 이용한 성적관리 프로그램 만들기1 (Score, ScoreDTO, ScoreImpl, ScoreMain, ScoreForm) 본문

JAVA_SE/11_io

[21.08.27] Interface 이용한 성적관리 프로그램 만들기1 (Score, ScoreDTO, ScoreImpl, ScoreMain, ScoreForm)

luvforjunk 2021. 8. 29. 16:37
728x90
반응형

프로그램을 구현하기 위해 5가지의 클래스를 만들어주었다.

 

1. ScoreMain : 메인메소드로, 단순히 호출하기 위해 만드 형식상의 클래스

2. ScoreDTO : 단 한명의 사람에 대한 성적 정보를 담고 있는 클래스(1인분값)

3. Score : 성적관리에 필요한 기능들(입력, 출력, 학번검색 기능 등)을 만들어주기 위한 기본 틀을 가지고 있는 추상클래스(인터페이스)

4. ScoreImpl : Score 인터페이스를 Override하는 클래스로, 본격적인 기능들을 담당하는 클래스

5. ScoreForm : 윈도우 창의 기본 레이아웃과 버튼 이벤트들을 담당하는 클래스. 

 

 

 

////////ScoreMain

 

package io;

 

public class ScoreMain {

 

        public static void main(String[] args) {

               new ScoreForm();

        }

}

 

////////ScoreDTO

 - 이 클래스의 핵심은 Serializable 인터페이스를 구현한다는 것인데, 이는 나중에 구현할 파일 입출력 할 때

이 클래스 전체를 꺼내고 입력받게 되는데 이 때 객체 직렬화를 진행해주지 않으면 에러로 인해 진행할 수 없게 된다.

직렬화를 시켜주기 위해서는 간단하게 Serializable 인터페이스를 implements해주면 된다.

하지만 모든 케이스가 단순히 인터페이스를 구현한다고 해서 다 가능하지는 않으며, 인터페이스를 상속받은 객체에

toString을 오버라이드해주면 직렬화가 완성된다. 

 

package io;

 

import java.io.Serializable;

 

public class ScoreDTO implements Serializable {

         private String hak;

         private String name;

         private int kor;

         private int eng;

         private int math;

         private int tot;

         private double avg;

 

         public String getHak() {

                  return hak;

         }

 

         public void setHak(String hak) {

                  this.hak = hak;

         }

 

         public String getName() {

                  return name;

         }

 

         public void setName(String name) {

                  this.name = name;

         }

 

         public int getKor() {

                  return kor;

         }

 

         public void setKor(int kor) {

                  this.kor = kor;

         }

 

         public int getEng() {

                  return eng;

         }

 

         public void setEng(int eng) {

                  this.eng = eng;

         }

 

         public int getMath() {

                  return math;

         }

 

         public void setMath(int math) {

                  this.math = math;

         }

 

         public int getTot() {

                  return tot;

         }

 

         public void setTot(int tot) {

                  this.tot = tot;

         }

 

         public double getAvg() {

                  return avg;

         }

 

         public void setAvg(double avg) {

                  this.avg = avg;

         }

}

 

////////Score(Interface)

 

package io;

 

import javax.swing.table.DefaultTableModel;

 

public interface Score {

 

        public void intput(ScoreDTO dto);

 

        public void print(DefaultTableModel model);

 

        public void search(DefaultTableModel model);

 

        public void tot_desc();

 

        public void save();

 

        public void load();

}

 

////////ScoreImpl

 

package io;

 

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectOutputStream;

import java.util.ArrayList;

import java.util.List;

import java.util.Vector;

 

import javax.swing.JFileChooser;

import javax.swing.JOptionPane;

import javax.swing.table.DefaultTableModel;

 

public class ScoreImpl implements Score {

         private List<ScoreDTO> list;

 

         public ScoreImpl() { // 생성자

                  list = new ArrayList<ScoreDTO>();

         }

 

         @Override

         public void intput(ScoreDTO dto) {

                  list.add(dto);

                  JOptionPane.showMessageDialog(null, "등록 완료"); // 여기선 This라는 Frame 없으니 null 잡아줌

         }

 

         @Override

         public void print(DefaultTableModel model) {

                  model.setRowCount(0); // RowCount(0) 의미는 안에 있는 모든 내용을 지우라는 의미

                  // 기존에 있는 지우고 새로이 입력한 값들이 들어오게끔!!!

                  // ex) [io.ScoreDTO@b20281a] 지우고 [io.ScoreDTO@b20281a, io.ScoreDTO@215d5581]

                  // 새로이 입력하면

                  // 우리 눈에는 [io.ScoreDTO@215d5581] 새롭게 들어온 것처럼 보인다

 

                  for (ScoreDTO dto : list) {// 모든 데이터가 list 죄다 쌓여 있다

                           Vector<String> v = new Vector<String>();

                           // 때마다 Vector 생겨야 한다. 한줄당 Vector 들어가니까

                           v.add(dto.getHak());

                           v.add(dto.getName());

                           v.add(dto.getKor() + ""); // 숫자를 문자열로 변환 - dto.getKor() int기본형이다

                           v.add(dto.getEng() + "");

                           v.add(dto.getMath() + "");

                           v.add(dto.getTot() + "");

                           v.add(String.format("%2f", dto.getAvg()));

 

                           model.addRow(v); // Table에다 Vector 붙이면 한줄이 붙게 되는 거지~~

                  } // for

         } // interface 구현체

 

         @Override

         public void search(DefaultTableModel model) {

                  String hak = JOptionPane.showInputDialog(null, "학번을 입력해주세요", "검색", JOptionPane.QUESTION_MESSAGE);

                  if (hak == null || hak.length() == 0)

                           return; // 만약에 취소버튼을 누르면 null 가져온다 - 취소버튼 누르면 그냥 나가라~

                 // hak.length() == 0 - 글씨를 넣지도 않았는데 확인버튼이 눌러지는 걸 막기위해 써주는 것이고, 
                 // 글자수가 0이면 입력을 안했다는 것을 의미

 

                  int sw = 0;

                  for (ScoreDTO dto : list) {

                           // = if(int i = 0; i<model.getRowcount(); i++) {

                           if (hak.equals(dto.getHak())) { // 학번이 테이블에 있는 학번이랑 같으냐

                                   model.setRowCount(0); // 테이블에 있는 값을 초기화시키고

 

                                   // list에서 꺼내온 내용을 Vector 집어넣는다

                                   Vector<String> v = new Vector<String>();

                                   v.add(dto.getHak());

                                   v.add(dto.getName());

                                   v.add(dto.getKor() + "");

                                   v.add(dto.getEng() + "");

                                   v.add(dto.getMath() + "");

                                   v.add(dto.getTot() + "");

                                   v.add(String.format("%2f", dto.getAvg()));

 

                                   model.addRow(v);

                                   sw = 1;

                           }

                  } // for

                  if (sw == 0)

                           JOptionPane.showMessageDialog(null, "찾고자 하는 학번이 없습니다");

 

         }

 

         @Override

         public void tot_desc() {

 

         }

 

         @Override

         public void save() {

                  JFileChooser chooser = new JFileChooser();

                  int result = chooser.showSaveDialog(null); // 저장 다이얼로그

                  // int result 받는 저장 버튼이 눌렸는지 취소버튼이 눌렸는지 알기 위해서다

 

                  File file = null;

                  if (result == JFileChooser.APPROVE_OPTION) { // save버튼 눌렀으면

                           file = chooser.getSelectedFile(); // 선택한 파일을 가져와라

 

                           // * 객체는 IO 통해서 못가니까 byte단위로 쪼개서 보내야 하는데

                           // 쪼개는 과정을 객체 직렬화한다고 한다

                           // byte 단위로 쪼개려면 DTO implements Serializable(직렬화) 입력

                           // Serializable 추상메소드가 없으니 Override시켜줄 것도 없다

                  }

                  // ----------------------------------

                  if (file == null)

                           return; // 파일에서 선택하지 않고 취소를 누르면 null값이 들어온다 나가라~~

                  try {

                           ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));

 

                           // 파일 집어넣기

                           for (ScoreDTO dto : list) {

                                   oos.writeObject(dto); // dto 넘겨줘라

                           } // for

 

                           oos.close();

                  } catch (IOException e) {

                           e.printStackTrace();

                  }

         }

 

         @Override

         public void load() {

 

         }

}

 

// Interface : Score(부모) - 추상메소드

// Class : ScoreImpl(자식) - ScoreService 대신

 

// 모든 데이터를 받아 데이터를 뿌리고 함수들의 입력 출력 등의 결과창이 있도록 하는 역할이

// 바로 ScoreImpl

// ScoreImpl 잡혀있는 모든 애들은 interface 거쳐야하며

// 구현부는 ScoreImpl

 

// 생성할 ScoreImpl impl = new ScoreImpl(); // 1 : 1 관계

// Score score = new ScoreImpl(); 같은 생성이지만 결합도를 낮춰준다

// Inteface 하나인데 Class 여러개로 넘쳐나면 Class 대표해 주는 것이 Interface(Score) 하나뿐이다

// 클래스는 여러개인데 참조하는 부모가 하나뿐인 것이 좋다

// 항상 접근은 부모걸로 접근하고 생성은 자식걸로 생성하는 것이 좋다

 

////////ScoreForm

 

package io;

 

import java.awt.Container;

import java.awt.GridLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.util.Vector;

 

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JTable;

import javax.swing.JTextField;

import javax.swing.table.DefaultTableModel;

 

public class ScoreForm extends JFrame implements ActionListener {

         private JLabel hakL, nameL, korL, engL, mathL;

         private JTextField hakT, nameT, korT, engT, mathT;

         private JButton inputBtn, printBtn, searchBtn, rankBtn, saveBtn, loadBtn;

         private DefaultTableModel model;

         private JTable table;

         private Score score; // inteface 잡기

 

         public ScoreForm() {

                  // JLabel 생성

                  hakL = new JLabel("학번");

                  nameL = new JLabel("이름");

                  korL = new JLabel("국어");

                  engL = new JLabel("영어");

                  mathL = new JLabel("수학");

 

                  // JTextField 생성

                  hakT = new JTextField("", 22); // 크기(22) 안주면 쪼그라든다

                  // TextField 크기가 없기 때문에 데이터가 들어갈 공간이 있어야 하니까 크기를 잡아준다

                  nameT = new JTextField("", 22);

                  korT = new JTextField("", 22);

                  engT = new JTextField("", 22);

                  mathT = new JTextField("", 22);

 

                  // JButton 생성

                  inputBtn = new JButton("입력");

                  printBtn = new JButton("출력");

                  searchBtn = new JButton("학번검색");

                  rankBtn = new JButton("순위");

                  saveBtn = new JButton("파일저장");

                  loadBtn = new JButton("파일읽기");

 

                  // JTable 타이틀

                  Vector<String> vector = new Vector<String>();

                  vector.add("학번");

                  vector.add("이름");

                  vector.add("국어");

                  vector.add("영어");

                  vector.add("수학");

                  vector.add("총점");

                  vector.add("평균");

 

                  model = new DefaultTableModel(vector, 0);

                  table = new JTable(model);

                  // 화면에 뿌려주는 Table. 안에서 데이터를 넣다 뺏다 하는 역할은 model 한다

                  JScrollPane scroll = new JScrollPane(table);

 

                  score = new ScoreImpl();

 

                  // Panel 생성

                  // West - 왼쪽

                  JPanel hakP = new JPanel(); // 학점 패널 위에

                  hakP.add(hakL); // 학점 라벨과

                  hakP.add(hakT); // 학점 텍스트필드를 넣어주고

                  JPanel nameP = new JPanel();

                  nameP.add(nameL);

                  nameP.add(nameT);

                  JPanel korP = new JPanel();

                  korP.add(korL);

                  korP.add(korT);

                  JPanel engP = new JPanel();

                  engP.add(engL);

                  engP.add(engT);

                  JPanel mathP = new JPanel();

                  mathP.add(mathL);

                  mathP.add(mathT);

 

                  JPanel p = new JPanel(new GridLayout(5, 1)); // 전체 패널 위에 균등하게 패널을 넣어줌(5, 1)

                  p.add(hakP); // 학점 패널

                  p.add(nameP); // 이름 패널

                  p.add(korP); // 국어 패널

                  p.add(engP); // 영어 패널

                  p.add(mathP); // 수학 패널

 

                  JPanel p2 = new JPanel(new GridLayout(1, 6, 5, 5)); // 다른 패널(p2) 입력, 출력, 학번검색, 순위, 파일저장, 파일읽기 버튼을 넣어줌

                  p2.add(inputBtn);

                  p2.add(printBtn);

                  p2.add(searchBtn);

                  p2.add(rankBtn);

                  p2.add(saveBtn);

                  p2.add(loadBtn);

 

                  Container c = getContentPane(); // 패널을 넣어줄 Container 생성

                  c.add("West", p); // 서쪽에 p

                  c.add("South", p2); // 남쪽에 p2

                  c.add("Center", scroll); // scroll 기본 센터에 배치

 

                  setBounds(900, 100, 700, 300);

                  setVisible(true);

                  setDefaultCloseOperation(EXIT_ON_CLOSE);

 

                  // 이벤트

                  event(); // event 함수 호출!

                  // 원래는 이벤트 안에 6개의 버튼들의 이벤트들이 들어올테지만

                  // 지금보다 훨씬 많은 이벤트들을 다룰 있으니 event함수를 적어놓고

                  // event메소드를 만든 호출 하는 식으로 만들어 것이다~~~

 

         } // ScoreForm() - 생성자 !

 

         // 메소드는 따로 잡을 있움

         public void event() {

                  inputBtn.addActionListener(this);

                  printBtn.addActionListener(this);

                  searchBtn.addActionListener(this);

                  rankBtn.addActionListener(this);

                  saveBtn.addActionListener(this);

                  loadBtn.addActionListener(this);

         }

 

         @Override

         public void actionPerformed(ActionEvent e) {

                  // 버튼들이 넘어오니까~

                  if (e.getSource() == inputBtn) { // 넘어오는 버튼이 inputBtn이냐~

                           input();

 

                           // 많은 데이터를 model에다 넣어야 하고 model Impl에다 뿌리려면 데이터를 보관해야 한다

                           // 데이터를 보관하려면 list 필요하다. (list 대신 DB 쓰기도)

 

                           // score.print(model);

                           // ScoreImpl에서는 JTable 있는지 없는지 모르니

                           // model 보내줘야한다 그래야 Table 관련된 일을 있다

                           // 데이터를 넣고 빼는 역할은 model 하고 있으니까

                           // score interface Score interface 만들어진다

 

                  } else if (e.getSource() == printBtn) { // printBtn이냐~

                           score.print(model);

                  } else if (e.getSource() == searchBtn) { // searchBtn이냐~

                           score.search(model);

                  } else if (e.getSource() == rankBtn) { // rankBtn이냐~

                           score.tot_desc();

                  } else if (e.getSource() == saveBtn) { // saveBtn이냐~

                           score.save();

                  } else if (e.getSource() == loadBtn) { // loadBtn이냐~

                           score.load();

                           score.print(model); // 파일 안에 있는 읽어오기

                  }

 

         } // actionPerformed(ActionEvent e)

 

         private void input() {

                  // JTextField 입력된 데이터 얻기

                  String hak = hakT.getText(); // hak TextField hak 데이터 가져오기

                  // 그렇담 데이터가 들어왔는 어떻게 확인할 있을까?

                  // = if(hak.equals("")) {

                  if (hak.length() == 0) { // 글자수가 0? 아무 문자도 들어오지 않았다는

                           JOptionPane.showMessageDialog(this, "학번을 입력하세요");

                           return;

                  }

                  String name = nameT.getText();

                  int kor = Integer.parseInt(korT.getText()); // TextField 들어오는 모두 문자열이다. 문자열 숫자로 바꿔버리자

                  int eng = Integer.parseInt(engT.getText()); //

                  int math = Integer.parseInt(mathT.getText());

 

                  // 계산

                  int tot = kor + eng + math;

                  double avg = (double) tot / 3;

 

                  ScoreDTO dto = new ScoreDTO();

                  // DTO 만들어서 ScoreDTO안에 데이터들을 한곳으로 모아야 데이터를 들고 다니기 편하다

                  dto.setHak(hak);

                  dto.setName(name);

                  dto.setKor(kor);

                  dto.setEng(eng);

                  dto.setMath(math);

                  dto.setTot(tot);

                  dto.setAvg(avg);

 

                  // 첫번째 방법 - ScoreDTO list 담아서 JTable 뿌리고...파일에 보관

                  score.intput(dto);

                  // 두번째 방법- ScoreDTO 가지고 ScoreDAO.java에서 DB insert한다

 

                  // 초기화 - 입력을 하고 저장하고 나면 다시 입력할 있도록 입력값을 초기화시켜줘야 한다

                  // 저장하고나서 글을 일일이 지워줄 없으니

                  hakT.setText("");

                  nameT.setText("");

                  korT.setText("");

                  engT.setText("");

                  mathT.setText("");

         }

}

 

// 입력 버튼을 누름과 동시에 ActionPerformed쪽으로 넘어와서 actionperformed에서 inputBtn입니까?

// 하고 확인한 input메소드로 보낸다

 

// 자바에선 null 하나의 상수로 인식한다

// 예를들어

// String a = null;                String b = "";

// a + "apple"                     b = "apple"

// "nullapple"                              "apple"

// -> 결합이나 연산에는 null 집어넣으면 안된다. null 자체가 들어가버리기 때문

 

// 자바가 제공하는 메소드는 throws 안된다

 

 

 

728x90
반응형