Daily Pogle

[OOP] 객체지향프로그래밍 - Object Oriented Programing 본문

Computer Science

[OOP] 객체지향프로그래밍 - Object Oriented Programing

pogles 2022. 12. 27. 10:52

1. 객체지향프로그래밍(OOP)

 

프로그래밍에서 필요한 데이터를 추상화 시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법

 


2. 객체지향 프로그래밍의 장점과 단점??

 

 

[장점]

  1. 코드 재사용 용이 | 타인이 만든 클래스를 가져와서 이용할 수 있고 상속을 통해 확장해서 사용할 수 있음
  2. 유지보수가 쉬움 | 수정해야 할 부분이 클래스 내부에 존재하기 때문에 해당 부분만 찾아서 수정
  3. 대형프로젝트에 적합 | 클래스 단위로 모듈화 시켜서 개발할 수 있기에 많은 인원(팀원, 회사)이 프로젝트를 개발할 때 업무 분담하기 쉬움.

 

[단점]

  1. 처리속도가 상대적으로 느림
  2. 객체가 많으면 용량이 커질 수 있음
  3. 설계시 많은 시간과 노력이 필요

3. 객체지향 5원칙(SOLID)

지켜야할 5가지 원칙

 

 

1) Single Responsibility Principle : 단일책임원칙.

객체는 오직 하나의 책임을 가져야한다.

 

  • 클래스의 목적을 명확히 함으로써 구조가 난잡해지고나 수정사항이 불필요하게 넓어지는 것을 예방한다.
  • 기능을 명확히 분리가능해야한다.

 

예시) 계산기 클래스 - 계산기를 포함하고 있는 어떤 프로그램이 전체적으로 수정된다고 하더라도 계산기 클래스는 사칙연산 기능만 책임지기 때문에, 사칙연산에 대한 수정이 필요하지 않으면 수정하지 않는다.

 

 

2) Open Closed Principle : 개방 폐쇄 원칙

객체는 확장에 대해서는 개방적이고 수정에 대해서는 폐쇄적이어야한다.

 

  • 객체기능의 확장을 허용하고, 변경은 피해야한다.

 

예시) 이동 기능을 구현할 때, 등속운동을 바탕으로 구현하였다. 그런데 특별한 이동기능이 필요할 때, 기존 구현한 등속운동을 수정하는 것이 아니라. 특별한 이동기능을 추가하는 것.

 

예시2) 스타크래프트에서 테란 건물에 대한 객체를 설정해 놓았는데, 배럭, 팩토리 등은 건물띄우기 기능이 있다. 그렇다면 테란 건물 객체를 수정하는 것이 아닌 건물 띄우기 기능을 추가한다. 

 

 

 

3) Liskov Sunstitution Principle : 리스코프 치환 원칙

자식클래스는 언제나 부모클래스를 대체할 수 있다는 원칙

 

  • 부모 클래스가 들어갈 자리에 자식 클래스를 넣어도 잘작동해야한다는 것. (상속의 본질)

 

 

4) Interface Segregation Principle : 인터페이스 분리 원칙

객체는 자신이 호출하지 않는 메서드에 의존하지 않아야한다.

 

  • 객체 구현 시 꼭 필요한 메서드만을 상속받거나 구현하도록 한다.
  • 상속할 객체의 메서드가 너무 방대하다면 상속할 객체의 메서드를 인터페이스로 분리하여, 인터페이스화 한 메서드만들 상속받고 구현하여 사용한다.

 

예시) 스마트폰 객체를 구현한다고 가정했을 때, 구형 스마트폰과 신형 스마트폰 모두 스마트폰 객체를 상속받는다. 이때 신형 스마트폰에서 지원하는 기능을 모두 포함하여 스마트폰 객체를 구현하게 된다면, 구형 스마트폰은 지원하지도 않는 기능을 상속받게 되고, 상속받았기에 불필요한 구현을 해야한다. 이때, 신형 스마트폰에서 지원하는 기능(메서드)를 인터페이스로 분리한다면, 구형 스마트폰에서는 해당 기능을 상속받지 않게 된다. 신형 스마트폰은 지원되는 기능을 스마트폰 객체가 아닌 분리된 인터페이스를 상속받아 사용하면 된다.

 

 

 

5) Dependency Inversion Principle : 의존성 역전 원칙

 

추상성이 높고 안정적인 고수준의 모듈은 구체적이고 불안정한 저수준의 모듈에 의존하면 안된다.

** 개방-폐쇄 원칙과 인터페이스 분리 원칙을 준수한다면 자연스럽게 따라오는 원칙

 

 

  • 고수준의 모듈은 객체의 형태나 추상적인 개념을 의미한다. >> 인터페이스, 추상클래스
  • 저수준의 모듈은 구체적인 기능이 포함되어 구현된 객체를 의미한다. >> 기능할 수 있는 코드가 구현되어있는 클래스

 

예시) GameUser 이라는 객체가 [ 캐릭터 이름, 체력, 마나, 무기형태 ] 를 입력받아 생성된다고 했을 때, 무기형태를 모든 무기를 포함하는 고수준의 모듈(추상클래스/인터페이스)가 아닌 weaponGun 으로 고정하여 사용하면(weaponGun 클래스에 의존하면), 모든 게임캐릭터(GameUser)는 weaponGun 의 무기형태를 가질 수 밖에 없다. 이와 같이 객체 생성 시 weaponGun 등의 저수준의 모듈에 의존하게 된다면 안된다. weaponForm 이라는 추상클래스에 의존시키고 weaponForm 안에는 weaponSword, weaponGun, weaponAxe 의 클래스가 포함시키는 방식을 사용해야한다.

 

 


의존성 역전의 원칙을 지키지 않은 코드 ( 객체생성시 무조건 WeaponGun 을 받음(WeaponGun에 의존함))

public class GameUser {
    private String name;
    private int hp;
    private WeaponGun weapon;
    
    // GameUser 객체는 WeaponGun 에 의존하게 됨
    public GameUser(String name, int hp, WeaponGun weapon) {
        this.name = name;
        this.hp = hp;
        this.weapon = weapon;
    }
}

public class WeaponGun {
    private String weaponName;
    private int durability;
    private int damage;
    
    public WeaponGun(String weaponName, int durability, int damage) {
        this.weaponName = weaponName;
        this.durability = durability;
        this.damage = damage;
    }
}

 

 

의존성 역전의 원칙을 지킨 코드

public class GameUser {
    private String name;
    private int hp;
    private WeaponGun weapon;
    
    // GameUser 객체는 WeaponForm 에 의존하게 됨
    public GameUser(String name, int hp, WeaponForm weapon) {
        this.name = name;
        this.hp = hp;
        this.weapon = weapon;
    }
}

// interface WeaponForm 에서 
public interface WeaponForm {
    int attack();
}

// 무기 : sword
public class WeaponSword implements WeaponForm {
    private String weaponName;
    private int durability;
    private int damage;
    
    public WeaponSword(String weaponName, int durability, int damage){
        this.weaponName = weaponName;
        this.durability = durability;
        this.damage = damage;
    }
    @Override
    public int attack() {
    }
}

// 무기 : Gun
public class WeaponGun implements WeaponForm {
    private String weaponName;
    private int durability;
    private int damage;
    
    public WeaponGun(String weaponName, int durability, int damage){
        this.weaponName = weaponName;
        this.durability = durability;
        this.damage = damage;
    }
    @Override
    public int attack() {
    }
}

// 무기 : Axe
public class WeaponAxe implements WeaponForm {
    private String weaponName;
    private int durability;
    private int damage;
    
    public WeaponAxe(String weaponName, int durability, int damage){
        this.weaponName = weaponName;
        this.durability = durability;
        this.damage = damage;
    }
    @Override
    public int attack() {
    }
}

'Computer Science' 카테고리의 다른 글

OSI 7 Layer (OSI 7계층)  (1) 2023.01.24
Process vs Thread  (0) 2023.01.22