지난 ver.1.0은 객체지향 설계, 클래스이용, 자료구조 이용 등을 고려하지 않고, 구현에만 집중했다고 했었다.
이후, 객체지향 프로그래밍을 좀 더 공부하며 이전보다 조금더 복잡도를 줄여서 리팩토링 할 수 있을까 고민해보았다.
이전에는 배열과 String을 통해서 데이터를 관리하고, GUI 클래스 내에 static 변수로 모든 데이터를 관리했었다.
ver.2.0에서는 Map 자료구조를 이용하였고, Person 클래스를 이용하여 관리하는것으로 변경해 보았다.
아직 많이 부족한것 같고, 딱 봐도 좀 지저분한 부분이 있는것 같지만, 자료구조를 응용하여 처음으로 프로그램에 적용해 보았고, 변경하면서 조금 더 정확히 이해하게된 측면이 있는 것 같다.
< 변경점 >
- 데이터 관리
- ver.1.0) 이름, 나이, 생일, 학번, 전화번호를 각각을 tab( \t ) 로 구분하여 문자열로 저장
- ver.2.0) Map<String, Person> 으로 관리 / Map의 key는 Person.getName()으로 사용
- 데이터베이스 - 이전과 동일하게 TextFile을 이용
- ver.1.0) 모든 정보를 TextFile에서 가져오고, 변경하며 관리
- ver.2.0) 모든 정보를 Map으로 관리, TextFile은 저장소의 역할만 한다.
package addressManagement;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.regex.Pattern;
public class AddressGUI extends JFrame {
String fname = "data/juso.txt";
static JTable table;
static String[] colNames = {"이름","나이","생일","학번","전화번호"};
static String[][] data = new String[50][5];
static JTextField nameSpace,studentNumSpace,ageSpace,birthDaySpace,phoneSpace;
public AddressGUI() throws IOException {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//종료버튼
setTitle("연락처 관리");// 제목 설정
setResizable(false);
this.setLayout(null);
PersonList firstList = new PersonList();
PersonList mainList = new PersonList();
mainList.setMainMap(firstList.getTextFile());
data = mainList.getDataArray();
//panel1----------------------------------------------------------------------
JPanel panel1 = new JPanel();
panel1.setLayout(new FlowLayout());
//연락처 출력 버튼
JButton printBtn = new JButton("연락처 출력");
printBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
tableRefresh(mainList);
}
});
panel1.add(printBtn);
//나가기 버튼
JButton exitBtn = new JButton(" 나가기 ");
exitBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
panel1.add(exitBtn);
//연락처 삭제 버튼, label
JLabel deleteAddress = new JLabel(" 삭제할 연락처(이름) : ");
panel1.add(deleteAddress);
JTextField delName = new JTextField(5);
panel1.add(delName);
JButton delete = new JButton("연락처 삭제");
delete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
int result = mainList.containsKeyCheck(delName.getText());
if(result==0) {
mainList.deletePerson(delName.getText());
}else if(result==1) {
JOptionPane error = new JOptionPane();
error.showMessageDialog(null, "삭제 란이 빈칸입니다.");
}else if(result==2){
JOptionPane error = new JOptionPane();
error.showMessageDialog(null, "존재하지 않는 이름입니다.");
}
tableRefresh(mainList);
try {
mainList.setTextFile();
} catch (IOException e) {
e.printStackTrace();
}
}
});
panel1.add(delete);
//panel 위치 설정
panel1.setBounds(10,10,850,40);// (x축, y축, 폭, 높이)
this.add(panel1);//setBounds로 정한 위치에 panel1 추가
//panel2 : 입력창 ---------------------------------------------------------------------------------------------------------
JPanel panel2 = new JPanel();
panel2.setLayout(new FlowLayout());
JLabel nameTxt,studentNumTxt,ageTxt,birthTxt,phoneTxt;
//label, TextField 배치
nameTxt = new JLabel(" 이름");panel2.add(nameTxt);
nameSpace = new JTextField(5);panel2.add(nameSpace);
ageTxt= new JLabel(" 나이");panel2.add(ageTxt);
ageSpace = new JTextField(3);panel2.add(ageSpace);
birthTxt= new JLabel(" 생일");panel2.add(birthTxt);
birthDaySpace = new JTextField(10);panel2.add(birthDaySpace);
studentNumTxt= new JLabel(" 학번");panel2.add(studentNumTxt);
studentNumSpace = new JTextField(8);panel2.add(studentNumSpace);
phoneTxt = new JLabel(" 전화번호");panel2.add(phoneTxt);
phoneSpace = new JTextField(12);panel2.add(phoneSpace);
//연락처 등록 버튼
JButton regist = new JButton("연락처 등록");
regist.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String errorMsg = judgeExp(getTexts());
if(errorMsg==""){
mainList.addPerson(makePerson());
}else{
JOptionPane error = new JOptionPane();//에러메시지 출력해주는 클래스
error.showMessageDialog(null, errorMsg);
}
tableRefresh(mainList);
try {
mainList.setTextFile();
setTextDefault();
} catch (IOException e) {
e.printStackTrace();
}
}
});
panel2.add(regist);
//panel2 위치 설정
panel2.setBounds(10,50,850,50);
this.add(panel2);
//panel3 : 테이블---------------------------------------------------------------------------------------------------
JPanel panel3 = new JPanel();
//연락처를 출력할 table 설정
String[][] data = new String[50][5];
String[] colNames = {"이름","나이","생일","학번","전화번호"};
table = new JTable(data,colNames);
JScrollPane sp = new JScrollPane(table);//scrollPane 에 테이블 위치시킴
table.setFillsViewportHeight(true);// scrollPane 안에 테이블을 꽉 차서 보이게 함
Dimension d = table.getPreferredSize();// d에서 설정한 사이즈를 넘어갈 시 스크롤바가 생성되도록 설정
d.width = 700;
d.height = 120;
sp.setPreferredSize(d);//스크롤바 생성
panel3.add(sp);
panel3.setBounds(0,100,850,200);
this.add(panel3);
setSize(850,280);// 윈도우 크기설정
setVisible(true);// 윈도우가 화면에 보임
}
static void tableRefresh(PersonList mainList){
data = mainList.getDataArray();
DefaultTableModel model = new DefaultTableModel(data,colNames);
table.setModel(model);
}
static Person makePerson(){
Person person = new Person(nameSpace.getText(), ageSpace.getText(), birthDaySpace.getText(), studentNumSpace.getText(), phoneSpace.getText());
return person;
}
static String[] getTexts(){
String[] infos = {nameSpace.getText(),ageSpace.getText(),birthDaySpace.getText(),studentNumSpace.getText(),phoneSpace.getText()};
return infos;
}
static void setTextDefault(){
nameSpace.setText("");
ageSpace.setText("");
birthDaySpace.setText("");
studentNumSpace.setText("");
phoneSpace.setText("");
}
static String judgeExp(String[] infos) {
String msg1 = "", msg2 = "", msg3 = "", msg4 = "", msg5 = "", msg6 = "";//에러뜨면 에러메시지에 추가할 문자열
String error = "";//위의 문자열중에 해당하는것만 error에 추가해줄
String wstr = "";
int ageCheck = 0;
String nameExp = "^[가-힣]*$|^[a-zA-Z]*$";//이름 pattern (형식) 포맷
String phoneExp = "(02|010)-\\d{3,4}-\\d{4}";//폰번호 포맷
String birthDayExp = "\\d{4}\\d{2}\\d{2}";//생일 포맷// infos[0] = nameif (!Pattern.matches(nameExp, infos[0])) {//패턴이 맞는지 확인하는 메소드
msg1 = "이름에는 한글 또는 영어만 입력 가능합니다.\n";
}
//infos[1] = ageif(infos[1].isEmpty()){
msg2 ="";
}
else if(Integer.parseInt(infos[1]) > 200) {
msg2 = "나이는 200살을 넘을 수 없습니다.\n";
}
//infos[2] = birthDayif (!Pattern.matches(birthDayExp, infos[2])) {
msg3 = "생일은 (ex.19980101)형식으로 입력해주세요.\n";
}
//infos[3] = studentNum / infos[4] = phoneNumif (!Pattern.matches(phoneExp, infos[4])) {
msg5 = "전화번호는 (ex.010-1234-5678)형식으로 입력해주세요\n";
}
if (infos[0].trim().isEmpty() || (ageCheck == 1) || infos[1].trim().isEmpty() || infos[2].trim().isEmpty() || infos[3].trim().isEmpty() || infos[4].trim().isEmpty()) {
msg6 = "\n!!!!!!!빈칸이 있습니다.!!!!!!!\n";
}//공백이 하나라도 있으면 맨 아래에 빈칸있다고 알려줌if ((msg1 != "") || (msg2 != "") || (msg3 != "") || (msg4 != "") || (msg5 != "") || (msg6 != "")) {
error = msg1 + msg2 + msg3 + msg4 + msg5 + msg6;//에러 뜬 부분은 위에서 msg1~6에 저장했음. error 변수에 다 합쳐줌return error;
}
else return "";
}
}
package addressManagement;
import java.util.regex.Pattern;
public class Person {
private String name;
private String age;
private String birthDay;
private String studentNum;
private String phoneNum;
public Person(String name, String age, String birthDay, String studentNum, String phoneNum) {
this.name = name;
this.age = age;
this.birthDay = birthDay;
this.studentNum = studentNum;
this.phoneNum = phoneNum;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getBirthDay() {
return birthDay;
}
public void setBirthDay(String birthDay) {
this.birthDay = birthDay;
}
public String getStudentNum() {
return studentNum;
}
public void setStudentNum(String studentNum) {
this.studentNum = studentNum;
}
public String getPhoneNum() {
return phoneNum;
}
public void setPhoneNum(String phoneNum) {
this.phoneNum = phoneNum;
}
}
package addressManagement;
import java.io.*;
import java.util.Hashtable;
import java.util.Map;
import java.util.regex.Pattern;
public class PersonList {
Map<String, Person> mainMap = new Hashtable<>();
static String fname = "C:\\dev_java_spring\\MyProject\\data\\juso.txt";
public void addPerson(Person person){
mainMap.put(person.getName(), person);
}
public void deletePerson(String s){
mainMap.remove(s);
}
public void setMainMap(Map<String, Person> mainMap) {
this.mainMap = mainMap;
}
public int containsKeyCheck(String delete){
//키가 있으면 0, 빈칸이면 1, 키가없으면 2if(mainMap.containsKey(delete)){
return 0;
}else if(delete.trim().isEmpty()){
return 1;
}else return 2;
}
public void setTextFile() throws IOException {
String data[][] = this.getDataArray();
try(FileOutputStream fos = new FileOutputStream(fname,false)){
}catch(IOException e){
e.printStackTrace();
}
BufferedWriter bw = new BufferedWriter(new FileWriter(fname));
for(int i=0;i<mainMap.size();i++){
String s = data[i][0]+"\t"+data[i][1]+"\t"+data[i][2]+"\t"+data[i][3]+"\t"+data[i][4];
bw.write(s);
bw.newLine();
}
bw.close();
}
public Map<String, Person> getTextFile() throws IOException{
Map<String, Person> map = new Hashtable<>();
BufferedReader br = new BufferedReader((new FileReader(fname)));
for(int i=0;;i++){
if(!br.ready())break;
else{
String str = br.readLine();
String[] personal = new String[5];
personal = str.split("\t");
Person person = new Person(personal[0],personal[1],personal[2],personal[3],personal[4]);
map.put(personal[0],person);
}
}
br.close();
return map;
}
public String[][] getDataArray(){
String data[][] = new String[50][5];
int first = 0;
for(String s : mainMap.keySet()){
Person man = mainMap.get(s);
for(int i=0;i<5;i++){
data[first][0] = man.getName();
data[first][1] = man.getAge();
data[first][2] = man.getBirthDay();
data[first][3] = man.getStudentNum();
data[first][4] = man.getPhoneNum();
}
first++;
}
return data;
}
}
package addressManagement;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
new AddressGUI();
}
}