회원가입

다형성 - 역할과 구현 예제

Beany 2024-11-03

ChatGPT 요약

이 블로그는 다형성에 대한 내용을 다루고 있습니다. 예제를 통해 역할과 구현을 분리한 코드와 그렇지 않은 코드의 차이를 설명하고 있습니다. 처음에는 구현과 역할을 분리하지 않은 코드를 통해 문제점을 보여주고, 다형성을 적용한 코드로 변경하면 클라이언트 코드의 변경 없이 구현 객체를 바꿀 수 있다는 장점을 설명하고 있습니다. 다형성을 사용하면 코드의 유지보수와 확장이 용이해집니다.

다형성 - 역할과 구현 예제


 

다형성 역하과 구현 예제 1

앞서 설명한 내용을 더 깊이있게 이해하기 위해, 간단한 운전자와 자동차의 관계를 개발해보자. 먼저 다형성을 사용하지 않고, 역할과 구현을 분리하지 않고 단순하게 개발해보자.

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()

 

 

다형성 역할과 구현 예제 2

새로운 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()
  • K3 를 운전하던 운전자가 Model3 로 차량을 변경해서 운전하는 코드이다.
  • driver.setK3Car(null) 을 통해서 기존 K3Car의 참조를 제거한다.
  • driver.setModel3Car(model3Car)를 통해서 새로운 model3Car 의 참조를 추가한다.
  • driver.drive() 를 호출한다.

여기서 새로운 차량을 추가한다면 또 다시 Driver 코드를 많이 변경해야 한다. 만약 운전할 수 있는 차량의 종류가 계속 늘어난다면? 점점 더 변경해야 하는 코드가 많아질 것이다.

자동차가 늘어나는데 Driver 의 코드를 계속 수정하는 것이 문제이다. 새로운 차가 등장할 때마다 Client 즉, Driver 는 그 정보를 계속 알고 분기 처리해야한다.

 

 

다형성 역할과 구현 예제 3

다형성을 활용하면 역할과 구현을 분리해서, 클라이언트 코드의 변경 없이 구현 객체를 변경할 수 있다.

다음 관계에서 Driver 가 클라이언트이다.

 

예제를 통해서 자세히 알아보자.

앞서 설명한 자동차 예제를 코드로 구현해보자.

  • Driver: 운전자는 자동차(Car)의 역할에만 의존한다. 구현인 K3, Model3 자동차에 의존하지 ㅇ낳는다.
    • Driver 클래스는 Car car 맴버 변수를 가진다. 따라서 Car 인터페이스를 참조한다.
    • 인터페이스를 구현한 K3Car, Model3Car 에 의존하지 않고, Car 인터페이스에만 의존한다.
    • 여기서 설명하는 의존은 클래스 의존 관계를 뜻한다. 클래스 상에서 어떤 클래스를 알고 있는가를 뜻한다. Driver 클래스 코드를 보면 Car 인터페이스만 사용하는 것을 확인할 수 있다.
  • Car: 자동차의 역할이고 인터페이스이다. K3Car, Model3Car 클래스가 인터페이스를 구현한다.

 

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()

 

0 0
JAVA
이 공간은 개인 공부를 통해 얻은 정보를 체계적으로 정리하고 공유하는 곳입니다. 학습한 내용, 발견한 지식, 그리고 문제 해결 방법 등을 기록하여 나만의 학습 자료를 구축하고, 필요할 때 쉽게 참고할 수 있는 유용한 자원으로 활용할 수 있도록 합니다.
Yesterday: 456
Today: 148