[Java] 객체 지향 프로그래밍

szlee·2023년 12월 6일
0

Java

목록 보기
12/23

< 김영한의 실전 자바 - 기본편 > 강의를 보고 이해한 내용을 바탕으로 합니다.





절차지향 vs 객체지향

절차 지향 프로그래밍

실행 순서를 중요하게 생각하는 방식이다.
프로그램의 흐름을 순차적으로 따르며 처리하는 방식이다. '어떻게'를 중심으로 프로그래밍

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;
    }
}

객체 지향 프로그래밍

객체를 중요하게 생각하는 방식이다.
실제 세계의 사물이나 사건을 객체로 보고, 이러한 객체들 간의 상호작용을 중심으로 프로그래밍 하는 방식이다. '무엇을' 중심으로 프로그래밍 한다.

위 코드에서 데이터 묶기

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;
    }
}

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

메서드 추출

위 코드에서 중복되는 부분이 존재 (볼륨 증가)
그리고 각각의 기능들은 이후에 재사용될 가능성이 높다.

  • 음악 플레이어 켜기, 끄기
  • 볼륨 증가, 감소
  • 음악 플레이어 상태 출력
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){
        if (data.isOn){
            System.out.println("음악 플레이어 ON, 볼륨:" + data.volume);
        } else{
            System.out.println("음악 플레이어 OFF");
        }
        System.out.println("음악 플레이어 상태 확인");
    }
}

각각의 기능을 메서드로 만들어 각각의 기능이 모듈화 되어 다음과 같은 장점을 얻을 수 있다.

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

객체지향과 절차지향 프로그래밍의 차이점은 뭘까?

절차지향은 데이터와 해당 데이터에 대한 처리 방식이 분리되어 있다.
반면 객체 지향에서는 데이터와 그 데이터에 대한 행동(메서드)이 하나의 객체 안에 함께 포함되어 있다.
⭐️객체 지향은 속성과 기능을 뭉쳐서 객체를 잘 만드는게 중요!!!⭐️

그렇더라도 이 둘은 서로 대치되는 개념이 아니다.
객체지향이더라도 프로그램의 작동 순서는 중요하다.
다만 어디에 더 초점을 맞추는가에 둘의 차이가 있다.

  • 객체지향 - 객체의 설계, 관계 중시
  • 절차지향 - 데이터와 기능이 분리되어있고 프로그램이 어떻게 작동하는지 순서에 초점을 맞춘다.

절차지향 프로그래밍의 한계?

지금까지 클래스를 사용해서 관련된 데이터를 하나로 묶고, 또 메서드를 사용해서 각각의 기능을 모듈화했다.

여기서 더 개선한다면?
작성한 코드의 한계는 데이터와 기능이 분리되어 있다는 점이다.
음악 플레이어의 데이터는 MusicPlayerData에 있는데 그 데이터를 사용하는 기능은 MusicPlayerMain3에 있는 각각의 메서드에 분리되어있다.
그래서 음악 플레이어와 관련된 데이터는 MusicPlayerData를 사용해야하고, 음악 플레이어와 관련된 기능은 MusicPlayerMain3의 각 메서드를 사용해야한다.

⭐️ 데이터와 그 데이터를 사용하는 기능은 매우 밀접하게 연관되어 있다.⭐️

각각의 메서드를 보면 대부분 MusicPlayerData의 데이터를 사용하는데 따라서 이후에 관련 데이터가 변경되면 MusicPlayerMain3 부분의 메서드들도 함께 변경해야 한다.
그리고 이렇게 데이터와 기능이 분리되어 있으면 유지보수 관점에서도 관리 포인트가 두곳으로 늘어난다.

객체 지향 프로그래밍이 나오기 전까지는 지금과 같이 데이터와 기능이 분리되어 있었다. --지금과 같은 코드가 최선이었다.
객체 지향 프로그래밍이 나오면서 데이터기능을 온전히 하나로 묶어서 사용할 수 있게 되었다.





클래스와 메서드

클래스데이터멤버 변수 뿐 아니라 기능 역할을 하는 메서드도 포함할 수 있다.

자바 같은 객체 지향 언어는 클래스 내부에 속성(데이터)과 기능(메서드)을 함께 포함할 수 있다.
클래스 내부에 멤버 변수 뿐만 아니라 메서드도 함께 포함할 수 있다는 것이다.

public class ValueData {
    int value;
    
    void add(){ 
        value++; //기본으로 본인 인스턴스에 있는 멤버 변수에 접근한다.
        System.out.println("숫자 증가 value=" + value);
    }
}

ValueData 클래스에 데이터인 value와 해당 데이터를 사용하는 기능인 add() 메서드를 함께 정의했다.
(메서드는 객체를 생성해야 호출할 수 있지만 static이 붙으면 객체를 생성하지 않고도 메서드를 호출할 수 있다.)

  • 클래스속성(데이터, 멤버변수)기능(메서드)을 정의할 수 있다.
  • 객체는 자신의 메서드를 통해 자신의 멤버 변수에 접근할 수 있다.
    • 객체의 메서드 내부에서 접근하는 멤버 변수 : 객체 자신의 멤버변수.




객체 지향 프로그래밍

음악 프로그래밍이라는 객체를 지향해보기
프로그램의 실행 순서 보다는 음악 플레이어 클래스를 만드는 것 자체에 집중하기.

음악 플레이어가 어떤 속성(데이터)을 가지고 어떤 기능(메서드)을 제공하는지 이 부분에 초점을 맞추기.
음악 플레이어를 만들어서 제공하는 개발자와 음악 플레이어를 사용하는 개발자가 분리되어 있다고 생각하기.

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(){
        if (isOn){
            System.out.println("음악 플레이어 ON, 볼륨:" + volume);
        } else{
            System.out.println("음악 플레이어 OFF");
        }
        System.out.println("음악 플레이어 상태 확인");
    }
}

MusicPlayer 클래스에 음악 플레이어에 필요한 속성과 기능을 모두 정의했다.
이제 음악 플레이어가 필요한 곳에서 이 클래스만 있으면 온전한 음악 플레이어를 생성해서 사용할 수 있다.
음악 플레이어를 사용하는데 필요한 모든 속성과 기능이 하나의 클래스에 포함되어 있다.

public class MusicPlayerMain4 {
    public static void main(String[] args) {
        MusicPlayer player = new MusicPlayer();

        //음악 플레이어 켜기
        player.on();
        //볼륨 증가
        player.volumeUp();
        //볼륨 증가
        player.volumeUp();
        //볼륨 감소
        player.volumeDown();
        //음악 플레이어 상태
        player.showStatus();
        //음악 플레이어 끄기
        player.off();

    }
}

MusicPlayer를 사용하는 입장

MusicPlayer 객체를 생성하고 필요한 기능(메서드)을 호출하기만 하면 된다.
필요한 모든 것은 MusicPlayer안에 들어있다.

  • MusicPlayer의 데이터인 volume, isOn과 같은 데이터는 전혀 사용하지 않는다.
  • 이제 MusicPlayer 내부에 어떤 속성(데이터)이 있는지 전혀 몰라도 된다.
    단순하게 제공하는 기능 중에 필요한 기능을 호출해서 사용하기만 하면 된다.



캡슐화

MusicPlayer를 보면 음악 플레이어를 구성하기 위한 속성과 기능이 마치 하나의 캡슐에 쌓여있는 것 같다.
이렇게 ⭐️속성과 기능을 하나로 묶어서 필요한 기능을 메서드를 통해 외부에 제공하는 것을 캡슐화⭐️라고 한다.

MusicPlayer 내부 코드가 변하는 경우 다른 코드는 변경하지 않아도 된다. MusicPlayervolume이라는 필드 이름이 다른 이름으로 변하면 MusicPlayer 내부만 변경하면 된다.
객체한테 물어보고 답을 얻기.

profile
🌱

0개의 댓글