객체지향프로그래밍

고동현·2024년 5월 27일
0

JAVA

목록 보기
4/22

절차 지향 프로그래밍

프로그래밍 방식은 객체지향 프로그래밍, 절차지향 프로그래밍 2가지로 나뉜다.
절차 지향은 데이터와 데이터에 대한 처리방식이 분리되어있는것이고,
객체지향에서는 데이터와 그 데이터에 대한 행동이 하나의 객체 안에 포함이 되어있다.

절차지향에서 객체 지향으로 점진적으로 코드를 변경해보면서 객체 지향 프로그래밍을 이해해보자.

음악 플레이어 만들기
요구사항:
음악플레이어를 켜고 끌수있고, 볼륨을 증가,감소할 수 있어야하고, 음악플레이어 상태를 확인할 수 있어야한다.

예시 출력:

음악 플레이어를 시작합니다
음악 플레이어 볼륨:1
음악 플레이어 볼륨:2
음악 플레이어 볼륨:1
음악 플레이어 상태 확인
음악 플레이어 ON, 볼륨:1
음악 플레이어를 종료합니다

절차지향 음악 플레이어1

public class MusicPlayerMain1 {
    public static void main(String[] args) {
        int volume =0;
        boolean isOn = false;

        isOn = true;
        System.out.println("음악 플레이어 시작");
         volume++;
        System.out.println("음악 플레이어 볼륨:" + volume);
        volume++;
        System.out.println("음악 플레이어 볼룸:"+volume);
        volume--;
        System.out.println("음악 플레이어 볼룸:"+volume);
        System.out.println("음악 플레이어 상태 확인");
        if(isOn){
            System.out.println("음악 플레이어 ON, 볼륨"+volume);
        }else{
            System.out.println("음악 플레이어 off");
        }

        isOn=false;
        System.out.println("음악 플레이어 종료");
    }
}

절차지향 음악 플레이어2 - 데이터 묶음

public class MusicPlayerData {
    int volume = 0;
    boolean isOn = false;
}
public class MusicPlayerMain2 {
    public static void main(String[] args) {
        MusicPlayerData data = new MusicPlayerData();

        data.isOn = true;
        System.out.println("음악 플레이어 시작");
        data.volume++;
        System.out.println("음악 플레이어 볼륨:" + data.volume);
        data.volume++;
        System.out.println("음악 플레이어 볼룸:"+data.volume);
        data.volume--;
        System.out.println("음악 플레이어 볼룸:"+data.volume);
        System.out.println("음악 플레이어 상태 확인");
        if(data.isOn){
            System.out.println("음악 플레이어 ON, 볼륨"+data.volume);
        }else{
            System.out.println("음악 플레이어 off");
        }

        data.isOn=false;
        System.out.println("음악 플레이어 종료");
    }
}

음악 플레이어와 관련된 데이터는 MusicPlayerData 클래스에 존재한다. 이후에 프로그램이 복잡해져서 다양한 변수들이 추가되더라도 음악 플레이어와 관련된 변수들은 MusicPlayerData data객체에 속해있으므로 구분하기 쉽다.

절차 지향 프로그래밍3 - 메서드 추출


public class MusicPlayerMain3 {
    public static void main(String[] args) {
        MusicPlayerData data = new MusicPlayerData();

        on(data);
        volumeUp(data);
        volumeUp(data);
        volumeDown(data);
        showStatus(data);
        off(data);
    }

    static void on(MusicPlayerData data){
        data.isOn = true;
        System.out.println("음악 플레이어를 시작합니다.");
    }
    static void off(MusicPlayerData data){
        data.isOn = false;
        System.out.println("음악 플레이어를 종료합니다.");
    }

    static void volumeUp(MusicPlayerData data){
        data.volume++;
        System.out.println("음악 플레이어 볼륨:"+data.volume);
    }

    static void volumeDown(MusicPlayerData data){
        data.volume--;
        System.out.println("음악 플레이어 볼륨:"+data.volume);
    }

    static void showStatus(MusicPlayerData data){
        System.out.println("음악 플레이어 상태 확인");
        if(data.isOn){
            System.out.println("음악 플레이어 ON,볼룸:"+ data.volume);
        }else{
            System.out.println("음악 플레이어 OFF");
        }
    }
}

이런식으로 메서드를 추출하면 더 깔끔한 코드를 구현할 수 있다.
이를통해

  • 중복제거: 로직 중복이 제거되었다. 같은 로직이 필요하면 해당 메서드를 여러번 호출하면된다.
  • 변경 영향 범위: 기능을 수정할 때 해당 메서드 내부만 변경하면 된다.
  • 메서드 이름 추가: 메서드 이름을 통해 코드를 더 쉽게 이해할 수 있다.

그러나 지금까지 한건 모두 절차 지향 프로그래밍이다.

절차 지향 프로그래밍의 한계
데이터와 기능이 분리되어있다는 점이다. 음악 플레이어의 데이터는 MusicPlayerData에 있는데, 그 데이터를 사용하는 기능은 MusicPlayerMain3에 있는 각각 메서드에 분리되어있다.

데이터와 그 데이터를 사용하는 기능은 매우 밀접하게 연관되어있으므로, 온전히 하나로 묶어서 사용해야만한다.

클래스와 메서드

public class ValueObject {
    int value;
    void add(){
        value++;
        System.out.println("숫자 증가 value="+value);
    }
}

이 클래스에는 데이터인 value와 해당 데이터를 사용하는 기능인 add()메서드를 함께 정의했다. 참고로 여기에는 static을 사용하지 않았는데 메서드는 객체를 생성해야 호출할 수 있다. 그런데 static을 사용하면 객체를 생성하지 않고도 만들 수 있기떄문에 value라는 필드에 관련된 메서드이라서 static을 붙이지 않았다.
자세한 static에 관한 내용은 뒤에서 설명할 것이다.

public class ValueObjectMain {
    public static void main(String[] args) {
        ValueObject valueObject =new ValueObject();
        valueObject.add();
        valueObject.add();
        System.out.println("최종 숫자 = "+valueObject.value);
    }
}

그림

add메서드를 호출하면 매ㅔ서드 내부에서 value++을 호출하게 되는데 이때 value에 접근해야하는데 기본으로 본인 인스턴스에 있는 멤버 변수에 접근한다.

객체지향 프로그래밍

데이터와 기능을 하나로 묶어서 음악 플레이어라는 개념을 온전히 하나의 클래스에 담아보자.

public class MusicPlayer {
    int volume = 0;
    boolean isOn = false;
    void on() {
        isOn = true;
        System.out.println("음악 플레이어를 시작합니다");
    }
    void off() {
        isOn = false;
        System.out.println("음악 플레이어를 종료합니다");
    }
    void volumeUp() {
        volume++;
        System.out.println("음악 플레이어 볼륨:" + volume);
    }
    void volumeDown() {
        volume--;
        System.out.println("음악 플레이어 볼륨:" + volume);
    }
    void showStatus() {
        System.out.println("음악 플레이어 상태 확인");
        if (isOn) {
            System.out.println("음악 플레이어 ON, 볼륨:" + volume);
        } else {
        }
        System.out.println("음악 플레이어 OFF");
    }
}
public class MusicPlayerMain4 {
    public static void main(String[] args) {
        MusicPlayer musicPlayer = new MusicPlayer();
        musicPlayer.on();
        musicPlayer.volumeUp();
        musicPlayer.volumeUp();
        musicPlayer.volumeDown();
        musicPlayer.showStatus();
        musicPlayer.off();
    }
}

MusicPlayer를 사용하는 입장에서는 실제 MusicPlayer에 어떤 필드가 있는지 알필요가 없다. 그냥 MusicPlayer에 정의된 메서드를 호출해서 사용하기만 하면된다.

캡슐화
MusicPlayer처럼 속성과 기능을 하나로 묶어서 필요한 기능을 메서드를 통해 외부에 제공하는것을 캡슐화라고 한다.
MusicPlayer내부 코드가 변경되더라도 다른 코드는 변경하지 않아도 된다는 장점이있다.

profile
항상 Why?[왜썻는지] What?[이를 통해 무엇을 얻었는지 생각하겠습니다.]

0개의 댓글