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)
을 잘 지키고 있는 코드라고 볼 수 있습니다.