- 자바 프로젝트 리팩토링 : Library Service(3)
동작이 잘하는지 테스트 겸 콘솔 실행을 하였는데 데이터가 3번 불러와졌다.
인스턴스 초기화 시점 때문에 그런 줄 알았으나, Singleton을 잘못 적용해서 그랬다.
Singleton 디자인 패턴에 대한 이해가 부족한 탓에 발생한 오류..😥
이번 기회에 Singleton에 대해 좀 더 심도 깊게 이해하게 되었다.
// 기존 코드
private static UserDao userDao;
private UserDao() {}
public static UserDao getInstance() { // 이 부분이 문제였다
return userDao ? null ? new UserDao() : userDao;
}
/* 변경 내용 */
private static UserDao userDao = new UserDao();
private UserDao() {}
public static UserDao getInstance() {
return userDao;
}
- User 기능 리팩토링
제일 먼저 리팩토링한 기능은 회원 기능이였다. (구현의 난이도가 대여 > 도서 > 유저 순이였다.)
구현부인 service와 저장부인 dao를 분리하였고, 변수명이나 로직을 깔끔하게 정리하였다.
기존 계정정보를 찾아오는 findUserbyID 메서드 또한 dao 안에서 조회할 수 있도록 바꾸었다.
로직 상 가장 많이 바뀌었던 부분은 권한 부여 부분이였다.
당시에는 처음 만드는 것이다 보니 깔끔하지 못한 로직이였는데 간결하고 가독성 있게 변경하였다.
- UserDao.java
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import domain.User;
import util.DataUtil;
public class UserDao {
// Singleton 패턴 적용
private static UserDao userDao;
private UserDao() {}
public static UserDao getInstance() {
return userDao == null ? new UserDao() : userDao;
}
private static List<User> users;
// User 데이터 초기화
static { users = DataUtil.initUsers(); }
// 계정정보 목록조회
public List<User> listUser() {
return users;
}
// 계정정보 조회
public User getUser(int id) {
for (User u : users) {
if (u.getId() == id) {
return u;
}
}
return null;
}
// 계정정보 생성
public void regUser(User user) {
users.add(user);
saveUser();
}
// 계정정보 수정
public void modifyUser(User user) {
User u = getUser(user.getId());
u.setName(user.getName());
u.setBirth(user.getBirth());
u.setPhone(user.getPhone());
saveUser();
}
// 계정정보 삭제
public void removeUser(User user) {
users.remove(user);
saveUser();
}
// 계정권한 변경
public void updateAuth(User user) {
User u = getUser(user.getId());
u.setAdmin(user.isAdmin());
u.setBlacklist(user.isBlacklist());
saveUser();
}
// User 데이터 저장
private void saveUser() {
ObjectOutputStream oos;
try {
oos = new ObjectOutputStream(new FileOutputStream("users.ser"));
oos.writeObject(users);
} catch (Exception e) {
e.printStackTrace();
}
}
}
- UserServiceImpl.java
package service.user;
import static util.LibUtil.convert;
import static util.LibUtil.convertLeft;
import static util.LibUtil.nextInt;
import static util.LibUtil.nextLine;
import java.util.List;
import dao.RentDao;
import dao.UserDao;
import domain.Rent;
import domain.User;
import util.LibUtil;
import util.StringUtil;
public class UserServiceImpl implements UserService {
private UserDao userDao = UserDao.getInstance();
private RentDao rentDao = RentDao.getInstance();
List<Rent> rents = rentDao.listRent();
@Override
public void listUser() {
List<User> users = userDao.listUser();
LibUtil.userIndex();
for (User user : users) {
System.out.print("│ " + convertLeft(StringUtil.userNameLength(user), 13) + " │ ");
System.out.print(convert(user.getBirth(), 6) + " │ ");
System.out.print(convert(user.getPhone(), 13) + " │ ");
System.out.print(convertLeft(userState(user), 10) + " │");
System.out.printf("%n──────────────────────────────────────────────────────────────────%n");
}
}
private String userState(User user) {
if ( user.isAdmin() ) {
return " 관리자";
} else if ( user.isBlacklist() ) {
return "블랙리스트";
} else {
return "";
}
}
@Override
public void regUser() {
User user = new User();
user.setName(nextLine("이름 > ", true, false));
user.setBirth(StringUtil.birthLength(nextLine("생년월일[ex)921024] > ", false, true)));
user.setPhone(StringUtil.pnLength(nextLine("전화번호[ex)01086940273] > ", false, true)));
user.setId(nextInt("ID > "));
user.setPw(nextLine("PW > "));
userDao.regUser(user);
System.out.println("계정생성이 완료되었습니다.");
}
@Override
public void modifyUser() {
User user = userDao.getUser(nextInt("수정할 계정의 ID > "));
if ( user != null ) {
System.out.println(user);
user.setName(nextLine("Enter the name to be replaced. > ", true, false));
user.setBirth(nextLine("Enter the birth to be replaced. > ", false, true));
user.setPhone(StringUtil.pnLength(nextLine("Enter the P.N to be replaced. >", false, true)));
userDao.modifyUser(user);
System.out.println("수정 완료 되었습니다.");
} else {
System.out.println("등록된 적 없는 ID입니다.");
}
}
@Override
public void removeUser() {
int id = nextInt("삭제할 회원의 ID를 입력하세요 > ");
User user = userDao.getUser(id);
int userID = 0;
for (Rent r : rents) { // Rent 수정 시 변경 예정
if ( user.getId() == r.getUserID() ) {
userID = r.getUserID();
break;
}
}
// userID가 없는 아이디일 경우
if ( user == null ) {
System.out.println("잘못된 ID입니다.");
}
// 대여 중인 도서가 있는 경우
else if ( userID != 0 ) {
System.out.println("대여 중인 도서가 있습니다.");
}
// 관리자 계정일 경우
else if ( user.isAdmin() ) {
System.out.println("해당 계정은 관리자 계정입니다.");
} else {
userDao.removeUser(user);
System.out.println("**삭제완료**");
}
}
@Override
public void updateAdmin(int id) {
User user = userDao.getUser(id);
if ( user != null ) {
if( user.isBlacklist() ) {
System.out.println("해당 계정은 블랙리스트입니다.");
} else if ( !user.isAdmin() ) {
user.setAdmin(true);
System.out.printf("%s님께 관리자 권한을 부여하였습니다.%n", user.getName());
} else {
user.setAdmin(false);
System.out.printf("%s님의 관리자 권한을 회수하였습니다.%n", user.getName());
}
userDao.updateAuth(user);
} else {
System.out.println("ID를 확인해주세요.");
}
}
@Override
public void updateBlackList(int id) {
User user = userDao.getUser(id);
if ( user != null ) {
if( user.isAdmin() ) {
System.out.println("관리자 계정입니다.");
} else if ( !user.isBlacklist() ) {
user.setBlacklist(true);
System.out.printf("%s님이 블랙리스트로 등록 되었습니다.%n", user.getName());
} else {
user.setBlacklist(false);
System.out.println("블랙리스트가 해제되었습니다.");
}
userDao.updateAuth(user);
} else {
System.out.println("ID를 확인해주세요.");
}
}
@Override
public int login(int id, String pw) {
User user = userDao.getUser(id);
if ( user != null ) {
if ( user.getPw().equals(pw) ) {
// 관리자 계정일 경우
if ( user.isAdmin() ) {
System.out.println();
System.out.println("관리자 계정입니다.");
return 1;
}
// 일반 계정일 경우
else {
System.out.println();
System.out.printf("%s님, 안녕하세요.%n", user.getName());
return 2;
}
}
}
// ID가 존재하지 않는 경우, PW가 일치하지 않는 경우
System.out.println();
System.out.println("ID 또는 pw를 확인해주세요.");
return 0;
}
}