Java 객체 지향 프로그래밍 기본
Java 의 객체 지향 프로그래밍을 배우기 전 절차 지향에 대해 알아보도록 한다.
절차 지향 프로그래밍
- 절차를 지향한다. 실행 순서를 중요하게 생각한다.
- 프로그램 흐름을 순차적으로 따라 처리하는 방식이다.
- 전체 코드를 어떻게 구성할 지 프로그래밍 한다.
객체 지향 프로그래밍
- 객체를 지향한다. 객체를 중점적으로 생각하는 방식이다.
- 실제 세계의 사물이나 사건을 객체로 보고, 객체들 간의 상호작용 중심으로 프로그래밍 하는 방식, 무엇을 중점적으로 프로그래밍 한다.
두 개의 프로그래밍 차이점
- 절차 지향은 데이터와 데이터 간 처리 방식이 분리되어 있다.
- 객체 지향은 데이터와 그 데이터에 대한 행동(메소드)이 하나의 객체 안에 함께 포함되어 있다.
절차 지향부터 프로그래밍 해보고 객체 지향 프로그래밍으로 변경해보도록 한다.
문제, 음악 플레이어 만들기 - 절차
음악 플레이어를 만들어 보도록 한다.
요구사항:
- 음악 플레이어를 끄고 킨다
- 음악 플레이어의 볼륨 증가, 감소한다.
- 음악 플레이어의 상태를 확인한다.
예시 출력:
음악 플레이어를 시작합니다.
음악 플레이어 볼륨:1
음악 플레이어 볼륨:2
음악 플레이어 볼륨:1
음악 플레이어 상태 확인
음악 플레이어 ON, 볼륨:1
음악 플레이어를 종료합니다.
풀이:
public class Main {
public static void main(String[] args) {
int volume = 0;
boolean isOn = false;
System.out.println("음악 플레이어를 시작합니다.");
isOn = true;
volume++;
System.out.println("음악 플레이어 볼륨: " + volume);
volume++;
System.out.println("음악 플레이어 볼륨: " + volume);
volume--;
System.out.println("음악 플레이어 볼륨: " + volume);
if (isOn) {
System.out.println("음악 플레이어 ON, 볼륨: " + volume);
} else {
System.out.println("음악 플레이어 OFF");
}
volume = 0;
isOn = false;
System.out.println("음악 플레이어를 종료합니다.");
}
}
절차대로 프로그래밍이 동작한다.
문제, 음악 플레이어 만들기 - 절차(클래스)
앞에서 작성한 코드를 수정하여 클래스를 도입한다. 음악 플레이어에 사용한 데이터를 클래스로 묶어 멤버변수로 활용한다.
음악 플레이어 - 데이터 묶음(클래스)
public static MusicPlayerData {
int volume = 0;
boolean isOn = false;
}
음악 플레이어에 사용한 volume, isOn 속성을 MusicPlayerData의 멤버 변수에 포함한다.
풀이
public class Main {
public static class MusicPlayerData {
int volume;
boolean isOn = false;
}
public static void main(String[] args) {
MusicPlayerData data = new MusicPlayerData();
System.out.println("음악 플레이어를 시작합니다.");
data.isOn = true;
data.volume++;
System.out.println("음악 플레이어 볼륨: " + volume);
data.volume++;
System.out.println("음악 플레이어 볼륨: " + volume);
data.volume--;
System.out.println("음악 플레이어 볼륨: " + volume);
if (data.isOn) {
System.out.println("음악 플레이어 ON, 볼륨: " + volume);
} else {
System.out.println("음악 플레이어 OFF");
}
data.volume = 0;
data.isOn = false;
System.out.println("음악 플레이어를 종료합니다.");
}
}
문제, 음악 플레이어 만들기 - 절차(메소드)
코드에서 중복 코드를 개선한다.
중복 코드
data.volume++;
System.out.println("음악 플레이어 볼륨: " + data.volume);
data.volume++;
System.out.println("음악 플레이어 볼륨: " + data.volume);
volume 멤버변수 값을 증감시킬 뿐 아니라 메시지가 출력되어야 하는데, 보다시피 중복 코드를 사용하고 있다.
그외의 각각의 기능들은 코드가 커질수록 재사용 될 가능성이 있다.
중복 가능성이 큰 기능
- 음악 플레이어 켜기, 끄기
- 음악 플레이어 볼륨 증가, 감소
- 음악 플레이어 상태 출력
위와 같은 기능을 메소드를 이용하여 구분한다.
public class Main {
public static class MusicPlayerData {
int volume;
boolean isOn = false;
}
public static void main(String[] args) {
MusicPlayerData data = new MusicPlayerData();
on(data);
volumeUp(data);
volumeUp(data);
volumeDown(data);
showStatus(data);
off(data);
}
public static void on(MusicPlayerData data) {
data.isOn = true;
System.out.println("음악 플레이어를 시작합니다.");
}
public static void volumeUp(MusicPlayerData data) {
data.volume++;
System.out.println("음악 플레이어 볼륨: " + data.volume);
}
public static void volumeDown(MusicPlayerData data) {
data.volume--;
System.out.println("음악 플레이어 볼륨: " + data.volume);
}
public static void off(MusicPlayerData data) {
data.isOn = false;
System.out.println("음악 플레이어를 종료합니다.");
}
public static void showStatus(MusicPlayerData data) {
if (data.isOn) {
System.out.println("음악 플레이어 ON, 볼륨: " + data.volume);
} else {
System.out.println("음악 플레이어 OFF");
}
}
}
각각의 기능을 메소드로 만들어 모듈화 되었다. 모듈화 장점은 다음과 같다.
- 중복 제거: 로직 중복이 제거되어 필요한 경우 메소드 하나를 여러번 호출한다.
- 변경 영향 범위: 기능 수정 시 해당 메소드 내부만 변경한다.
- 메서드 이름: 메소드 이름을 통해 이 코드가 어떤 역할 및 행동을 하는지 쉽게 이해 할 수 있다.
절차 지향 프로그래밍 한계
코드에서 데이터를 묶고, 메소드를 이용한 모듈화도 성공적으로 완료하였다. 이로 인해 읽기 좋고, 유지보수 용이한 코드를 완성시킬 수 있다.
하지만 이 코드의 한계는 데이터와 기능이 분리되어 있음을 확인할 수 있다. 음악 플레이어 데이터는 MusicPlayerData 가 들어가는데, 이 데이터를 사용하는 기능은 Main 클래스의 각각의 메소드로 분리되어 개발되어 있다. 음악 플레이어 데이터는 MusicPlayerData를 사용해야 했고, 음악 플레이어와 관련된 기능은 Main 클래스의 메소드를 이용할 수밖에 없다.
데이터와 이 데이터를 사용하는 기능은 매우 밀접하게 연관되고, 각각의 메소드에서는 MusicPlayerData 멤버변수를 사용하였다. 데이터가 변경되면 Main 클래스의 메소드도 함께 변경해야하고 유지보수 관점에서도 두 곳으로 늘어난다.
앞 서 만든 코드는 절차 지향 프로그래밍으로서 최선이다. 이제 객체 지향 프로그래밍으로 데이터와 기능가 하나로 묶어 사용해보도록 한다.