Post

Java 문법 (13) - 다형성과 설계

Java 문법 (13) - 다형성과 설계




좋은 객체지향 프로그래밍


객체지향에는 추상화, 캡슐화, 상속, 다형성의 특징이 있는데 이 중 다형성이 가장 중요하다고 볼 수 있습니다. 객체지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러개의 독립된 단위, 객체들의 모임으로 파악하고자 하는 것입니다. 각각의 객체들은 메시지를 주고받고 데이터를 처리할 수 있습니다.

객체 지향 프로그래밍은 프로그램을 유연하고 변경이 용이하게 만들기 때문에 대규모 소프트웨어 개발에 많이 사용됩니다. 마치 레고 블럭을 조립하듯이, 컴퓨터 부품을 갈아 끼우듯이 컴포넌트를 쉽고 유연하게 변경하면서 개발할 수 있는 방법입니다.




다형성

역할과 구현으로 구분하면 세상이 단순해지고, 유연해지며 변경도 편리해집니다.

  • 클라이언트는 대상의 역할만 알면 됨
  • 클라이언트는 구현 대상의 내부구조를 몰라도 됨
  • 클라이언트는 구현 대상의 내부 구조가 변경되어도 영향을 받지 않음
  • 클라이언트는 구현 대상 자체를 변경해도 영향을 받지 않음

이를 운전자와 자동차의 관계에 비유하면 다음과 같습니다.

  • 운전자는 자동차의 역할만 알면 되고, 내부구조를 몰라도 됩니다.
  • 자동차의 내부구조가 변경되어도 운전자는 영향을 받지 않습니다.
  • 운전자는 차를 바꿔도 영향을 받지 않습니다.

자바 언어에서는 역할 = 인터페이스 / 구현 = 인터페이스를 구현한 클래스, 구현 객체로 볼 수 있습니다. 객체 설계시 역할을 먼제 부여하고, 그 역할을 수행하는 구현 객체를 만들어야 합니다. 또한 객체의 협력이라는 관계를 생각해야합니다. 수많은 객체 클라이언트(요청)와 서버(응답)는 서로 협력 관계를 가집니다.




다형성 - 역할과 구현 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Driver.java  
public class Driver {  
    private Car car;  
  
    public void setCar(Car car){  
        this.car = car;  
    }  
  
    public void drive() {  
        System.out.println("자동차를 운전합니다");  
        car.startEngine();  
        car.pressAccelerator();  
        car.offEnngine();  
    }  
}
1
2
3
4
5
6
// Car.java
public interface Car {  
    void startEngine();  
    void pressAccelerator();  
    void offEnngine();  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// K3Car.java
public class K3Car implements Car {  
    public void startEngine(){  
        System.out.println("K3Car.startEngine");  
    }  
  
    public void offEnngine() {  
        System.out.println("K3Car.offEnngine");  
    }  
  
    public void pressAccelerator(){  
        System.out.println("K3Car.pressAccelerator");  
    }  
  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Model3Car.java  
public class Model3Car implements Car{  
    public void startEngine(){  
        System.out.println("Model3Car.startEngine");  
    }  
  
    public void offEnngine() {  
        System.out.println("Model3Car.offEnngine");  
    }  
  
    public void pressAccelerator(){  
        System.out.println("Model3Car.pressAccelerator");  
    }  
  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// CarMain1.java  
public class CarMain1 {  
    public static void main(String[] args) {  
        Driver driver = new Driver();  
        K3Car k3Car = new K3Car();  
  
        driver.setCar(k3Car);  
        driver.drive();  
  
        // 추가  
        Model3Car model3Car = new Model3Car();  
        driver.setCar(model3Car);  
        driver.drive();  
  
        NewCar newCar = new NewCar();  
        driver.setCar(newCar);  
        driver.drive();  
    }  
}

Driver는 Car의 역할에만 의존합니다. 구현인 K3와 Model3 자동차에는 의존하지 않습니다. 새로운 차량이 추가되어도 Dirver의 코드는 전혀 수정하지 않아도 됩니다. 이는 확장에 열려있고, 수정에는 닫혀있는 코드로 OCP원칙(Open-Closed Principle)을 잘 지키고 있는 코드라고 볼 수 있습니다.