Programming

; develop a program

Back-End/Java

[Java] 인터페이스와 다형성

Clloud_ 2023. 2. 9. 15:52
반응형

이번 포스팅에서는 자바(Java)에서 인터페이스와 다형성에 대하여 공부를 해보고자 한다.

 


인터페이스의 역할

인터페이스는 클라이언트 프로그램에 어떤 메서드를 제공하는지 미리 알려주는 명세(sepcification) 또는 약속의 역할을 한다.

인터페이스는 디폴트 메서드와 정적 메서드 구현부(implementation part)가 없다면 무용지물이다.

 

예를 들어 Abc 인터페이스를 구현한 A클래스와 이 클래스를 사용하는 Z 프로그램이 있다고 가정했을 때, ABC 인터페이스에는 구현할 추상 메서드가 모두 선언되어 있고, 어떤 메개변수가 사용되는지, 어떤 자료형 값이 반환되는지 선언되어 있다.

즉 Z 프로그램에서는 A 클래스의 구현 코드 전체를 살펴보지 않고 Abc 인터페이스의 선언부만 봐도 이 A 클래스를 어떻게 사용할지 알 수 있다.

 

만약 Z 프로그램에서 Abc 인터페이스를 구현한 다른 클래스인 B를 사용하고 싶다면, 인터페이스 명세에 따라 A 클래스에서 B 클래스로 교체해서 사용할 수 있다.

A, B, C 클래스가 모두 Abc 인터페이스를 구현했다면, 다음과 같이 Z 프로그램에서 Abc를 클래스 형으로 선언하여 코드를 작성할 수 있다.

Abc abc;
abc = new A();
abc = new B();
abc = new C();
  • 각 클래스를 사용할 때 클래스에서 구현한 내용을 몰라도 Abc 인터페이스에서 선언한 메서드의 매개변수 자료형과 반환 값만 알면 Abc 인터페이스를 구현한 어떤 클래스든 사용할 수 있다.

 


인터페이스와 다형성

인터페이스를 사용하면 다형성을 구현하여 확장성 있는 프로그램을 만들 수 있다.

즉 클라이언트 프로그램을 많이 수정하지 않고 기능을 추가하거나 다른 기능을 사용할 수 있다.

 

예제

'고객 상담 전화 배분 프로그램' 만들기

 

구현할 배분 방식

  1. 순서대로 배분(RoundRobin): 모든 상담원이 동일한 상당 건수를 처리하도록 들어오는 전화 순서대로 상담원에게 하나씩 배분한다.
  2. 짧은 대기열 찾아 배분(LeastJob): 고객 대기시간을 줄이기 위해 상담을 하지 않는 상담원이나 가장 짧은 대기열을 보유한 상담원에게 배분한다.
  3. 우선순위에 따라 배분(PriorityAllocation): 고객 등급에 따라 등급이 높은 고객의 전화를 우선 가져와서 업무 능력이 좋은 상담원에게 우선 배분

 

클래스 설계도

 

  • Scheduler 인터페이스에는 1~3에서 모두 공통으로 사용하는 메서드를 선언한다.
  • getNexCall( )은 다음 전화를 가져오는 기능, sendCallToAgent( )는 상담원에게 전화를 배분하는 기능을 담당한다.
  • Scheduler 인터페이스가 두 개의 추상 메서드를 선언했기 때문에 해당 인터페이스를 구현하는 각 클래스도 모두 추상 메서드 2개를 구현해야 한다.

 

Scheduler 인터페이스 정의

public interface Scheduler {
    public void getNextCall();
    public void sendCallToAgent();	
}
  • Scheduler 인터페이스는 추상 메서드 2개를 선언한다.

 

RoundRobin 클래스

//상담원 한명씩 돌아가며 동일하게 상담업무를 배분합니다.
public class RoundRobin implements Scheduler{
    @Override
    public void getNextCall() {
        System.out.println("상담 전화를 순서대로 대기열에서 가져옵니다");	
    }

    @Override
    public void sendCallToAgent() {
        System.out.println("다음 순서 상담원에게 배분합니다.");	
    }
}

 

  • RoundRobin 클래스는 예제 시나리오 1을 구현한 것이다.
  • 고객센터에 걸려온 상담 전화를 순서대로 가져와서 상담원에게 배분한다.

 

LeastJob 클래스

// 현재 상담업무가 없거나 상담대기가 가장 작은 상담원에게 배분합니다.
public class LeastJob implements Scheduler{
    @Override
    public void getNextCall() {
        System.out.println("상담 전화를 순서대로 대기열에서 가져옵니다");	
    }

    @Override
    public void sendCallToAgent() {
        System.out.println("현재 상담업무가 없거나 상담대기가 가장 작은 상담원에게 할당합니다.");
    }
}
  • 고객 센터에 걸려온 상담전화를 순서대로 가져와서 현재 상담 업무가 없거나 상담 대기가 가장 적은 상담원에게 배분한다.

 

PriorityAllocation 클래스

// 고객등급이 높은 고객부터 대기열에서 가져와 업무 능력이 높은 상담원 우선으로 배분합니다.
public class PriorityAllocation implements Scheduler{
    @Override
    public void getNextCall() {
        System.out.println("고객 등급이 높은 고객의 전화를 먼저 가져옵니다.");
    }
    
    @Override
    public void sendCallToAgent() {
        System.out.println("업무 skill 값이 높은 상담원에게 우선적으로 배분합니다.");
    }
}
  • 고객 센터에서 걸려온 상담 전화 중 고객 등급이 높은 고객의 전화를 먼저 가져와서 업무 능력이 가장 좋은 상담원에게 배분한다.

 

입력 문제에 따라 배분 정책을 정하고 실행하는 프로그램

public class SchedulerTest {
    public static void main(String[] args) throws IOException {
        System.out.println("전화 상담 할당 방식을 선택 하세요.");
        System.out.println("R : 한명씩 차례로 할당 ");
        System.out.println("L : 쉬고 있거나 대기가 가장 적은 상담원에게 할당 ");
        System.out.println("P : 우선순위가 높은 고객 먼저 할당 ");

        //할당 방식을 입력받아 ch 변수에 대입
        int ch = System.in.read();
        Scheduler scheduler = null;

        //입력받은 값이 R 또는 r이면 RoundRobin 클래스 생성
        if(ch == 'R' || ch == 'r'){
            scheduler = new RoundRobin();
        }
        //입력받은 값이 L 또는 l이면 LeastJob 클래스 생성
        else if(ch == 'L' || ch == 'l'){
            scheduler = new LeastJob();
        }
        //입력받은 값이 P 또는 p이면 PriorityAllocation 클래스 생성
        else if(ch == 'P'|| ch == 'p'){
            scheduler = new PriorityAllocation();
        }
        else{
            System.out.println("지원되지 않는 기능입니다.");
            return;
        }

        //어떤 정책인가와 상관없이 인터페이스에 선언한 메서드 호출
        scheduler.getNextCall();
        scheduler.sendCallToAgent();
    }
}
  • 9행에서 문자를 입력받으면 입력 문자에 해당하는 배분 정책 클래스를 생성하여 대입한다.
  • RoundRobin, LeastJob, PriorityAllocation 클래스로 생성한 인스턴스는 모두 Scheduler형 변수에 대입할 수 있다.
  • 사용할 인스턴스가 어떤 클래스로 생성되었는지와 상관없이 30~31행처럼 인터페이스에서 제공하는 메서드를 호출하면 된다.
    (인터페이스를 활용해 다형성을 구현)

 


클라이언트가 클래스를 사용하는 방법

위에서 정의한 상담 전화 배분 정책은 언제든지 바뀔 수 있다.

이러한 경우 추가로 만들어야 하는 배분 정책은 Scheduler 인터페이스를 구현하는 새 클래스로 만들면 된다.

어떤 클래스를 구현하건 클라이언트가 인터페이스를 구현한 클래스를 사용하는 방식은 다음 코드와 같다.

scheduler.getNextCall();
scheduler.sendCallToAgent();

 

클라이언트 프로그램은 각 클래스의 구현 방법을 몰라도 인터페이스에서 선언된 매개변수, 반환 값을 보고 클래스를 사용할 수 있다.

 

 

인터페이스는 구현된 클래스를 사용하는 클라이언트 코드와 기능을 제공하는 코드 사이의 약속이다.

 


반응형

'Back-End > Java' 카테고리의 다른 글

[Java] Object 클래스  (0) 2023.02.10
[Java] 인터페이스 요소  (0) 2023.02.10
[Java] 인터페이스(Interface)  (0) 2023.02.09
[Java] final 예약어  (0) 2023.02.08
[Java] 템플릿 메서드(Template Method)  (0) 2023.02.07