앞서 설명한 내용을 더 깊이있게 이해하기 위해, 간단한 운전자와 자동차의 관계를 개발해보자. 먼저 다형성을 사용하지 않고, 역할과 구현을 분리하지 않고 단순하게 개발해보자.
Driver 는 K3Car 를 운전하는 프로그램이다.
package poly.car0;
public class K3Car {
public void startEngine() {
System.out.println("K3Car.startEngine()");
}
public void offEngine() {
System.out.println("K3Car.offEngine()");
}
public void pressAccelerator() {
System.out.println("K3Car.pressAccelerator()");
}
}
package poly.car0;
public class Driver {
private K3Car k3Car;
public void setK3Car(K3Car k3Car) {
this.k3Car = k3Car;
}
public void drive() {
System.out.println("Driver.drive");
k3Car.startEngine();
k3Car.pressAccelerator();
k3Car.pressAccelerator();
k3Car.offEngine();
}
}
package poly.car0;
public class CarMain0 {
public static void main(String[] args) {
Driver driver = new Driver();
K3Car k3Car = new K3Car();
driver.setK3Car(k3Car);
driver.drive();
}
}
Driver.drive
K3Car.startEngine()
K3Car.pressAccelerator()
K3Car.pressAccelerator()
K3Car.offEngine()
새로운 Model3 차량을 추가해야 하는 요구사항이 들어왔다. 이 요구사항을 맞추려면 기존에 Driver 코드를 많이 변경해야 한다.
Driver 는 K3Car 도 운전할 수 있고, Model3Car 도 운전할 수 있어야 한다. 참고로 둘을 동시에 운전하는 것은 아니다.
package poly.car0;
public class Model3Car {
public void startEngine() {
System.out.println("Model3Car.startEngine()");
}
public void offEngine() {
System.out.println("Model3Car.offEngine()");
}
public void pressAccelerator() {
System.out.println("Model3Car.pressAccelerator()");
}
}
package poly.car0;
public class Driver {
private K3Car k3Car;
private Model3Car model3Car;
public void setK3Car(K3Car k3Car) {
this.k3Car = k3Car;
}
public void setModel3Car(Model3Car model3Car) {
this.model3Car = model3Car;
}
public void drive() {
System.out.println("Driver.drive");
if (k3Car != null) {
k3Car.startEngine();
k3Car.pressAccelerator();
k3Car.pressAccelerator();
k3Car.offEngine();
} else if (model3Car != null) {
model3Car.startEngine();
model3Car.pressAccelerator();
model3Car.pressAccelerator();
model3Car.offEngine();
}
}
}
package poly.car0;
public class CarMain0 {
public static void main(String[] args) {
Driver driver = new Driver();
K3Car k3Car = new K3Car();
driver.setK3Car(k3Car);
driver.drive();
// 추가
Model3Car model3Car = new Model3Car();
driver.setModel3Car(model3Car);
driver.setK3Car(null);
driver.drive();
}
}
Driver.drive
K3Car.startEngine()
K3Car.pressAccelerator()
K3Car.pressAccelerator()
K3Car.offEngine()
Driver.drive
Model3Car.startEngine()
Model3Car.pressAccelerator()
Model3Car.pressAccelerator()
Model3Car.offEngine()
여기서 새로운 차량을 추가한다면 또 다시 Driver 코드를 많이 변경해야 한다. 만약 운전할 수 있는 차량의 종류가 계속 늘어난다면? 점점 더 변경해야 하는 코드가 많아질 것이다.
자동차가 늘어나는데 Driver 의 코드를 계속 수정하는 것이 문제이다. 새로운 차가 등장할 때마다 Client 즉, Driver 는 그 정보를 계속 알고 분기 처리해야한다.
다형성을 활용하면 역할과 구현을 분리해서, 클라이언트 코드의 변경 없이 구현 객체를 변경할 수 있다.
다음 관계에서 Driver 가 클라이언트이다.
예제를 통해서 자세히 알아보자.
앞서 설명한 자동차 예제를 코드로 구현해보자.
package poly.car1;
public interface Car {
void startEngine();
void offEngine();
void pressAccelerator();
}
package poly.car1;
public class K3Car implements Car {
@Override
public void startEngine() {
System.out.println("K3Car.startEngine()");
}
@Override
public void offEngine() {
System.out.println("K3Car.offEngine()");
}
@Override
public void pressAccelerator() {
System.out.println("K3Car.pressAccelerator()");
}
}
package poly.car1;
public class Model3Car implements Car {
@Override
public void startEngine() {
System.out.println("Model3Car.startEngine()");
}
@Override
public void offEngine() {
System.out.println("Model3Car.offEngine()");
}
@Override
public void pressAccelerator() {
System.out.println("Model3Car.pressAccelerator()");
}
}
package poly.car1;
public class Driver {
private Car car;
public void setCar(Car car) {
this.car = car;
}
public void drive() {
System.out.println("Driver.drive");
this.car.offEngine();
this.car.startEngine();
this.car.pressAccelerator();
}
}
package poly.car1;
public class CarMain1 {
public static void main(String[] args) {
Driver driver = new Driver();
driver.setCar(new K3Car());
driver.drive();
driver.setCar(new Model3Car());
driver.drive();
}
}
Driver.drive
K3Car.offEngine()
K3Car.startEngine()
K3Car.pressAccelerator()
Driver.drive
Model3Car.offEngine()
Model3Car.startEngine()
Model3Car.pressAccelerator()