- 여러 개의 계좌를 관리하는 프로그램
( 클래스 3개 생성 )
1. BankAccount.java (계좌정보 자체의 표현 담당) (조회, 변경 그 자체의 기능만 있음)
필드: 계좌번호, 예금주, 비밀번호, 잔액
기능: 계좌정보 출력기능,
잔액 변경기능, 비밀번호 변경기능, (Setter 메소드)
계좌번호 조회기능, 비밀번호 조회기능, 잔액 조회기능 (Getter 메소드)
// 계좌정보를 표현하는 클래스
// 계좌정보 하나를 저장하는 객체를 생성할 때 사용되는 클래스
// Value Object ( 단순한 형태 - 필드 , 생성자 , Getter, Setter )
// 필드 중심
public class BankAccount {
// 필드
private String no;
private String name;
private int password;
private int balance;
// 생성자 메소드
public BankAccount(String no, String name, int password, int balance) {
// Getter 메소드
public String getNo() { return no; }
public String getName() { return name; }
public int getPassword() { return password; }
public int getBalance() { return balance; }
// Setter 메소드
public void setNo(String no) { this.no = no; }
public void setName(String name) { this.name = name; }
public void setPassword(int password) { this.password = password; }
public void setBalance(int balance) { this.balance = balance; }
2. Banking.java (사용자의 요청 처리 (업무로직 수행))
필드: 계좌정보 여러 개 저장하는 배열
기능: 신규 계좌정보 등록 기능, 계좌정보 조회 기능, 입금 서비스, 출금 서비스, 비밀번호 변경 서비스, 해지 서비스
// 업무로직을 표현하는 클래스
// 업무로직(Business Logic, Service Logic)이 포함된 메소드를 제공하는 객체
// Service Object
// 기능 중심
public class Banking {
// 신규 계좌 개설 메소드
public void createAccount(String no, String name, int password, int amount) {
// 신규 계좌 개설 업무로직
}
// 계좌정보 조회 메소드
public BankAccount findAccount(String no) {
// 계좌정보 조회 업무로직
}
// 입금 업무로직
public void deposit(String no, int amount) {
// 입금 업무로직
-현재 잔액 조회-
int currentBalance = account.getBalance();
-현재 잔액에 입금액 더하기-
int updateBalance = currentBalance + amount
-변경된 현재 잔액을 Account객체에 대입하기-
account.setBalance(updateBalance);
}
// 출금 업무로직
public int withdraw(String no, int password, int amount) {
// 출금 업무로직
-비밀번호 조회-
int password = account.getPassword();
-비밀번호 체크-
if (password != inputPassword) {
s.o.p("비밀번호가 일치하지 않습니다.");
return;
}
-잔액 조회-
int currentBalance = account.getBalance();
-잔액 체크-
if (currentBalance < 출금액) {
s.o.p("잔액이 부족합니다.");
return;
}
-현재 잔액에서 출금액만큼 감액-
int updateBalance = currentBalance - amount;
-변경된 현재 잔액을 Account객체에 대입-
account.setBalance(updateBalance);
}
// 비밀번호 변경 업무로직
public void changePassword(String no, int prevPassword, int password) {
// 비밀번호 변경 업무로직
}
// 개설된 모든 계좌정보 출력 업무로직
public void printAllAccount( ) {
// 모든 계좌정보 출력 업무로직
}
3. BankingApp.java (사용자와 상호작용 담당)
메인: -서비스 메뉴 제공-
1.등록 2.조회 3.입금 4.출금 5.해지 0.종료
-사용자와 상호작용-
사용자가 입력할 내용을 안내한다.
사용자의 입력을 읽어온다.
-업무로직 실행-
사용자가 요청한 업무로직을 실행한다.
<실습>
- BankingAccount (정보 담당)
/**
* 계좌정보를 표현하는 클래스
* @author wnnns
*
*/
public class BankAccount {
private String no;
private String name;
private int password;
private int balance;
/**
* 계좌정보를 초기화하는 생성자
* @param no 계좌번호
* @param name 예금주
* @param password 비밀번호
* @param balance 계좌 생성시 입금할 최초 잔액
*/
public BankAccount(String no, String name, int password, int balance) {
this.no = no;
this.name = name;
this.password = password;
this.balance = balance;
}
/**
* 계좌번호 반환
* @return 계좌번호
*/
public String getNo() {
return no;
}
/**
* 예금주 반환
* @return 예금주 이름
*/
public String getName() {
return name;
}
/**
* 비밀번호 반환
* @return 비밀번호
*/
public int getPassword() {
return password;
}
/**
* 현재 잔액 반환
* @return 현재 잔액
*/
public int getBalance() {
return balance;
}
/**
* 새 비밀번호를 전달받아서 비밀번호를 변경한다.
* @param password 새 비밀번호
*/
public void setPassword(int password) {
this.password = password;
}
/**
* 변경된 잔액을 전달받아서 현재 잔액을 변경한다.
* @param balance 변경된 잔액
*/
public void setBalance(int balance) {
this.balance = balance;
}
/**
*
* 계좌정보를 화면에 출력하는 메소드
*/
public void displayAccount() {
System.out.println("["+name+"] 님의 계좌정보");
System.out.println("계좌번호: " + no);
System.out.println("예금주: " + name);
System.out.println("비밀번호: " + (password/100)+"**");
System.out.println("현재잔액: " + balance + "원");
System.out.println();
}
}
- Banking (업무로직)
/**
* 은행 업무(신규 계좌개설, 조회, 입금, 출금, 비밀번호변경, 해지 등)가 구현된 클래스다.
* @author wnnns
*
*/
public class Banking {
// 개설된 계좌정보객체를 저장하는 배열객체 생성. (BankAccout객체를 100개 담을 수 있음)
private BankAccount[] accounts = new BankAccount[100];
// 개설된 계좌정보객체가 저장되는 위치를 저장하는 변수 생성
private int index = 0;
public Banking() { //기본생성자 (객체 생성하자마자 실행할 수행문)
// createAccount()메소드를 실행시켜서 Banking객체가 생성되면 계좌5개를 배열객체에 추가시킨다.
createAccount("11-11-111", "김유신", 1234, 50000);
createAccount("11-11-222", "강감찬", 1234, 150000);
createAccount("11-11-333", "이순신", 1234, 350000);
createAccount("11-11-444", "류관순", 1234, 450000);
createAccount("11-11-555", "홍길동", 1234, 550000);
}
/**
* 신규 계좌개설기능
* <p>계좌번호, 예금주, 비밀번호, 최초 입금액을 전달받아서 신규 계좌를 개설한다.
* @param no 계좌번호
* @param name 예금주
* @param password 비밀번호
* @param amount 최초 입금액
*/
public void createAccount(String no, String name, int password, int amount) {
// 신규 계좌정보 객체를 생성
BankAccount account = new BankAccount(no, name, password, amount); // BankAccount 클래스 연결
// 생성된 계좌정보 객체를 accounts배열의 지정된 위치에 저장한다.
accounts[index] = account;
// index 값을 1증가시킨다.
index++;
}
/**
* 개설된 전체 계좌정보 목록 출력
*/
public void printAllAccounts() {
System.out.println("### 전체 계좌 목록");
System.out.println("-----------------------------------------");
System.out.println("계좌번호\t\t예금주\t비밀번호\t잔액");
System.out.println("-----------------------------------------");
for(BankAccount account : accounts) {
if(account == null) {
break;
}
System.out.print(account.getNo() + "\t");
System.out.print(account.getName() + "\t");
System.out.print(account.getPassword()/100 + "**\t");
System.out.println(account.getBalance());
}
System.out.println("-----------------------------------------");
}
/**
* 계좌 조회기능
* <p>계좌번호를 전달받아서 계좌번호에 해당하는 계좌정보를 반환한다.
* @param no 조회할 계좌번호
* @return 계좌정보를 포함하고 있는 BankAccount객체
*/
public BankAccount findAccount(String no) {
// 전달받은 계좌번호와 일치하는 계좌정보를 배열에서 찾아서 그 계좌정보객체의 참조값을 저장할 변수를 생성한다.
BankAccount account = null; // 1) 반환타입에 해당하는 account 변수를 만들어서 초기화
// accounts 배열에 저장된 BankAccout객체의 주소값을 처음부터 순서대로 하나씩 item변수에 대입하고, 수행문 실행
for(BankAccount item : accounts) {
// item이 null이 아닐때를 먼저 설정 (item에 저장된 주소값이 null이면 반복문 탈출)
if(item == null) {
break;
}
// item에 저장된 주소값이 null이 아니면,
// item이 참조하는 BankAccount객체의 getNo()메소드를 실행해서 그 객체의 계좌번호를 획득한다.
// getNo()메소드를 실행해야 반환값으로 no를 얻음 -> 얘를 accountNo 변수에 저장
String accountNo = item.getNo();
// 반환값으로 얻은 계좌번호와 매개변수로 전달받은 계좌번호가 일치하는 체크한다.
if(accountNo.equals(no)) {
// 계좌번호가 일치하면, item에 저장된 BankAccount객체의 주소값을 account에 저장하고, 반복문 탈출
account = item;
break;
}
}
// account변수에 저장된 BankAccount객체의 주소값 반환
// 단, 전달받은 계좌번호와 일치하는 계좌정보가 없는 경우 null이 반환
return account; //만들때는 null로 초기화하고 2) return값도 변수로 설정해
}
/**
* 입금기능
* <p>계좌번호와 입금액을 전달받아서 해당 계좌의 잔액을 입금액만큼 증가시킨다.
* @param no 계좌번호
* @param amount 입금액
*/
public void deposit(String no, int amount) {
// 전달받은 계좌번호에 해당하는 계좌정보를 조회한다.
BankAccount account = findAccount(no); //find메소드 실행 (일치하는 계좌번호가 있는 BankAccount객체의 주소값을 account에 저장)
// 계좌가 존재하는지부터 찾기
// 조화된 계좌정보가 null이면 메소드 종료
if(account == null) {
System.out.println("### 계좌번호와 일치하는 계좌정보가 존재하지 않습니다.");
return; //빠른 종료
}
// 여기부터는 이제 account값이 무조건 있는 것
// 현재 잔액을 조회해서 current변수에 대입
int currentBalance = account.getBalance();
// 현재 잔액에 입금액을 더한 값을 계산하고 update변수에 대입
int updateBalance = currentBalance + amount;
// 계좌의 현재 잔액을 변경한다.
account.setBalance(updateBalance);
System.out.println("### 입금이 완료되었습니다.");
}
/**
* 출금기능
* <p>계좌번호, 비밀번호, 출금액을 전달받아서 해당 계좌의 잔액을 출금액만큼 감소시키고, 출금액만큼의 금액을 반환한다.
* @param no 계좌번호
* @param password 비밀번호
* @param amount 출금액
* @return 인출된 금액
*/
public int withdraw(String no, int password, int amount) {
int withdrawAmount = 0; // 1) int를 반환하네? -> int withdrawAmount =0; 으로 초기화
// 전달받은 계좌정보에 해당하는 계좌정보 조회
BankAccount account = findAccount(no); // 일치하는 계좌번호가 있는 BankAccount객체의 주소값을 account에 저장
// 조회된 계좌정보가 null이면 메소드 종료
if(account == null) {
System.out.println("### 계좌번호와 일치하는 계좌정보가 존재하지 않습니다.");
return 0;
}
// 비밀번호 체크
int accountPassword = account.getPassword();
if(accountPassword != password) {
System.out.println("### 비밀번호가 일치하지 않습니다.");
return 0; // 틀린경우 빠른 종료
}
// 잔액 체크
int currentBalance = account.getBalance();
if(currentBalance < amount ) {
System.out.println("### 잔액이 부족합니다.");
return 0;
}
// 잔액을 출금액만큼 감소시키고, 계좌의 잔액을 변경시킨다.
int updateBalance = currentBalance - amount - 1200; //수수료 1200원
account.setBalance(updateBalance);
withdrawAmount = amount;
return withdrawAmount; // 2) return withdrawAmount 로 설정
}
/**
* 비밀번호 변경 기능
* <p>계좌번호, 이전 비밀번호, 새 비밀번호를 전달받아서 해당 계좌의 비밀번호를 변경한다.
* @param no 계좌번호
* @param prevPassword 이전 비밀번호
* @param password 새 비밀번호
*/
public void changeAccountPassword(String no, int prevPassword, int password) {
// 전달받은 계좌정보에 해당하는 계좌정보 조회
BankAccount account = findAccount(no); //일치하는 계좌번호가 있는 BankAccount객체의 주소값을 account에 저장
if(account == null) {
System.out.println("### 계좌번호와 일치하는 계좌정보가 존재하지 않습니다.");
return; // void라서 return 0;이라고 안함
}
// 비밀번호 체크
int accountPassword = account.getPassword();
if(accountPassword != prevPassword) {
System.out.println("### 비밀번호가 일치하지 않습니다.");
return;
}
// 이전 비밀번호와 새 비밀번호가 일치하는지 체크
if(prevPassword == password) {
System.out.println("### 이전 비밀번호와 같은 번호로 변경할 수 없습니다.");
return;
}
// 계좌의 비밀번호를 새 비밀번호로 변경
account.setPassword(password);
System.out.println("### 비밀번호가 변경되었습니다.");
}
}
- BankingApp (상호작용)
import utils.KeyboardReader;
public class BankingApp {
public static void main(String[] args) {
// 키보드 입력을 읽어오는 기능이 구현된 객체 생성
KeyboardReader keyboard = new KeyboardReader();
// 은행업무 기능이 구현된 객체 생성 (Banking클래스 연결)
Banking banking = new Banking();
while(true) {
System.out.println("----------------------------------------------------------");
System.out.println("1.계좌개설 2.계좌조회 3.입금 4.출금 5.비밀번호변경 6.전계좌조회 0.종료");
System.out.println("----------------------------------------------------------");
System.out.print("메뉴 선택: ");
int menuNo = keyboard.getInt();
System.out.println();
if(menuNo == 1) {
System.out.println("<< 신규 계좌 개설 >>");
// 신규 계좌 개설이 필요한 정보를 입력받는다.
System.out.print("신규 계좌번호 입력: ");
String no = keyboard.getString(); // '-'가 포함되어있어서?
System.out.print("에금주 입력: ");
String name = keyboard.getString();
System.out.print("신규 계좌 비밀번호 입력: ");
int password = keyboard.getInt();
System.out.print("신규 계좌 최초 입금액 입력: ");
int amount = keyboard.getInt();
// Banking 객체의 createAccount() 메소드를 실행해서 신규계좌를 개설한다.
banking.createAccount(no, name, password, amount);
} else if(menuNo == 2) {
System.out.println("<< 계좌 정보 조회 >>");
System.out.print("조회할 계좌번호 입력: ");
String no = keyboard.getString();
// 반환값이 BankAccount니까
// Banking 객체의 findAccount() 메소드를 실행해서, 전달한 계좌번호와 일치하는 계좌정보를 반환
// 그 반환된 결과를 account 변수에 저장
BankAccount account = banking.findAccount(no);
if(account != null) {
account.displayAccount();
} else { // account가 null일 때
System.out.println("### 계좌정보가 존재하지 않습니다.");
}
} else if(menuNo == 3) {
System.out.println("<< 입금하기 >>");
System.out.print("입금할 계좌번호 입력: ");
String no = keyboard.getString();
System.out.print("입금액 입력: ");
int amount = keyboard.getInt();
banking.deposit(no, amount);
} else if(menuNo == 4) {
System.out.println("<< 출금하기 >>");
System.out.print("출금할 계좌번호 입력: ");
String no = keyboard.getString();
System.out.print("계좌 비밀번호 입력: ");
int password = keyboard.getInt();
System.out.print("출금액 입력: ");
int amount = keyboard.getInt();
int withdrawAmount = banking.withdraw(no, password, amount); //출력하기 위해서 변수에 저장
System.out.println("### ["+withdrawAmount+"] 원을 출금하였습니다.");
} else if(menuNo == 5) {
System.out.println("<< 비밀번호 변경하기 >>");
System.out.print("계좌번호 입력: ");
String no = keyboard.getString();
System.out.print("이전 비밀번호 입력: ");
int prevPassword = keyboard.getInt();
System.out.print("새 비밀번호 입력: ");
int password = keyboard.getInt();
banking.changeAccountPassword(no, prevPassword, password);
} else if(menuNo == 6) {
System.out.println("<< 전체 계좌 조회 >>");
banking.printAllAccounts();
} else if(menuNo == 0) {
System.out.println("<< 프로그램 종료 >>");
break; //while문 빠져나가기
}
System.out.println(); //명령마다 간격
System.out.println();
}
System.out.println("### 프로그램이 종료되었습니다. ###");
}
}
- 신규 계좌 개설 업무로직
* Banking.java (업무로직 클래스) 실행과정
- public class Banking {
Banking이라는 업무로직 객체가 있어 - private BankAccount[] accounts = new BankAccount[100];
private int index = 0;
BankAccount (정보 담당)클래스에 적은 계좌 정보를 여러개 담을 수 있는 배열 객체 생성
이 객체 안에 있는 변수 accounts, index는 private이라서 안보이고, 0으로 초기화되어있어
-> 변수 accounts 안에는 BankAccount배열 100개를 담을 수 있는 배열객체 BankAccount[ ]의 주소값
( = Banking객체 안의 accounts변수가 배열객체를 참조(연결))
-> 이 배열객체 안에 있는 length변수에는 100이 들어가 있고 (길이가 100짜리임),
-> 그리고 index값이 지금 0으로 초기화되어 있어 - public void createAccount(String no, String name, int password, int amount) {
계좌번호, 예금주, 비밀번호, 최초잔액을 입력받아서 신규계좌를 개설하는 createAccount 메소드 생성
-> 메소드 안에는 no, name, password, amount 변수가 있어
-> 이제 누가 createAccount메소드를 실행하면, - BankAccount account = new BankAccount(no, name, password, amount);
메소드의 매개변수로 받은 값들을 BankAccount (정보 담당) 클래스의 멤버변수에 대입해야되는데,
Banking 클래스랑 BankAccount 클래스의 연결이 안되어 있음
+ 아직 BankAccount의 배열객체 한 칸에 들어가는 객체가 없음!
배열객체가 있으면, 그 배열객체 한칸을 다루기 위해서 배열객체랑 같은 타입의 객체를 생성해야돼
-> BankAccount 배열객체에 들어갈, BankAccount 타입의 객체를 생성
-> BankAccount 객체가 생성되면 동시에 초기화가 됨(생성자메소드라서) -> no, name, password, balance변수가 키보드로 입력한 값으로 초기화됨
-> 이 객체의 주소를 account 변수에 저장해 (=연결)
-> 배열객체와 배열이 연결 - accounts[index] = account;
근데 지금 index 값이 0이니까 accounts가 참조하는 배열객체의 0번째 칸에 account가 참조하는 객체가 연결돼
( = BankAccount[ ] 배열의 인덱스 한 칸에 BankAccount() 객체 하나를 연결 )
(= BankAccount[ ] 배열객체와 BankAccount 객체 연결)
그 BankAccount (정보 담당) 객체에는 처음에 만든 객체의 변수, 메소드들이 있어 - index++;
그리고 배열을 다 채워야되니까 index를 1 증가시킴
index와 BankAccount배열객체는 메소드 밖에 있으니깐 index가 1 증가하고 BankAccount배열의 1번째 칸으로 옮겨진 채로 메소드가 종료돼, 계속 진행할 수 있는 것.
실행했을 때, 6번 전체계좌조회 할 때 값을 다 입력 안하고 실행하면
nullpointerror가 뜨는 이유
0번째에는 값이 들어있는데 1번째부터는 값이 없어 = null 이야
그러면 참조할 게 없으니까 오류
-> null일때의 경우를 추가해줌
=> if (account == null) { break; ) 를 추가
* BankApp.java (상호작용 클래스) 실행과정
- Banking banking = new Banking();
Banking (업무로직) 클래스와 연결을 해서, 그 변수와 기능을 이용할거야
-> Banking객체를 생성하고, 그 주소값을 banking변수가 가짐
(= BankApp가 Banking을 참조) - banking.createAccount(no, name, password, amount);
신규계좌개설 메소드 실행
BankApp(상호작용) 클래스에서 신규계좌개설 메소드를 호출하면 Banking(업무로직) 클래스에 있는 메소드 실행
-> banking 변수가 가리키는 객체의 createAccount메소드를 실행 - banking.printAllAccount();
전체 계좌정보 출력 메소드 실행
- 계좌 조회하기 (입력한 계좌번호와 일치하는 계좌번호의 정보 출력)
* BankingApp (상호작용) 객체 실행과정
- Banking banking = new Banking();
상호작용 클래스(BankingApp)와 업무로직 클래스(Banking)를 연결 - s.o.p("조회할 계좌번호 입력: ");
String no = keyboard.getString(); - BankAccount account = banking.findAccount(no);
키보드로 입력받은 no를 매개변수로 전달,
banking이 참조하는 객체의 find메소드를 실행하고, 메소드 실행 후 얻은 반환결과를 account 변수에 저장
( 메소드 실행은 아래 Banking 실행과정 보기 )
메소드의 반환값이 BankAccount 타입이기 때문에 BankAccount 타입의 변수 account에 저장함
if (account != null) { // 반환결과가 null이 아니라면
account.displayAccount( ); // account변수가 참조하는 객체의 display메소드 실행
} else {
s.o.p("계좌정보가 존재하지 않습니다.")
}
* Banking (업무로직) 객체 실행과정
- BankAccount[] accounts = new BankAccount[100];
BankAccount 클래스에 적은 계좌정보를 여러개 담는 배열객체 - public BankAccount findAccount(int no) {
입력한 계좌번호와 일치하는 계좌번호의 정보 출력하는 메소드
반환타입이 BankAccount ( BankAccount(정보담당) 클래스에 있는 변수를 찾아야돼서? )
1) BankingApp(상호작용) 객체에서 키보드로 입력한 no(계좌번호) 값을 메소드의 매개변수로 전달하고,
Banking(업무로직) 객체의 find메소드 매개변수에 그 no(계좌번호) 값을 대입
2) find 메소드 실행 - BankAccount account = null;
반환값이 BankAccount 타입이므로, 먼저 BankAccount 타입의 참조변수 account를 생성해서 초기화 - for (BankAccount item : accounts) {
accounts가 가리키는 배열객체에서 BankAccount 객체를 뽑아서 BankAccount타입의 변수 item에 하나씩 저장
( BankAccount 배열객체에서 나온 BankAccount 객체이므로, BankAccount 타입의 변수에 저장 )
근데 신규계좌개설하는 메소드에서 BankAccount 배열객체의 0번째 인덱스의 값을 저장했음 (0x1111)
3) accounts 배열의 0번째 인덱스의 값(0x1111)을 item에 먼저 저장 (item이 0x1111의 BankAccount 객체를 참조함) - String accountNo = item.getNo();
item이 바라보는 객체 (BankAccount객체 0x1111)의 getNo()메소드를 실행하고, 그 반환값(0x1111의 no)을 accountNo에 저장 - if (accountNo.equals(no)) {
account = item;
break;
}
만약 이 원래 0x1111의 no의 값과 키보드로 입력한 no가 일치하면,
item의 주소값(0x1111)을 account변수에 저장
( = account변수도 item이 참조하고 있는 객체 (BankAccount객체 0x1111)를 참조함) - } // for문 종료
return account;
}
account값 (주소값 0x1111)을 반환해
4) 반환된 account값이 BankingApp객체의 메소드 결과값으로 들어감
* BankingApp 객체의 account변수에 왜 0x1111주소값이 들어가는지 꼭 알아야 함
- 3-tier 구조의 시스템 ( 우리가 앞으로 이렇게 만들거야 )
우선은 왼쪽으로 배우고 세미프로젝트
목표는 오른쪽이고 파이널프로젝트
'수업내용 > Java' 카테고리의 다른 글
[2022.09.21.수] 생성자 메소드, 클래스형변환 (0) | 2022.09.21 |
---|---|
[2022.09.20.화] static, 상속 (0) | 2022.09.20 |
[2022.09.17.토] 숙제1 (0) | 2022.09.18 |
[2022.09.16.금] 생성자, this (0) | 2022.09.17 |
[2022.09.15.목] 메소드의 매개변수, 반환타입, 중복정의 (0) | 2022.09.16 |