3 분 소요

1. 인터페이스의 개념

인터페이스는 클래스와 관련된 계약을 정의하는데 사용되는 키워드이다. 인터페이스를 구현하는 클래스는 해당 인터페이스에 정의된 모든 멤버를 구현해야 한다. 이를 통해 다형성을 지원하고, 코드 재사용성과 유연성을 높일 수 있다.

먼저 인터페이스를 어떻게 구현하는지 예시를 통하여 알아보자.

// IShape 인터페이스 정의
public interface IShape
{
    double CalculateArea(); // 면적 계산 메서드 선언
    void Display(); // 출력 메서드 선언
}

// Circle 클래스가 IShape 인터페이스를 구현함
public class Circle : IShape
{
    private double radius;

    public Circle(double radius)
    {
        this.radius = radius;
    }

    public double CalculateArea()
    {
        return Math.PI * radius * radius;
    }

    public void Display()
    {
        Console.WriteLine($"Circle with radius {radius}");
        Console.WriteLine($"Area: {CalculateArea()}");
    }
}

// Rectangle 클래스가 IShape 인터페이스를 구현함
public class Rectangle : IShape
{
    private double width;
    private double height;

    public Rectangle(double width, double height)
    {
        this.width = width;
        this.height = height;
    }

   public double CalculateArea()
   {
       return width * height;
   }

   public void Display()
   {
       Console.WriteLine($"Rectangle with width {width} and height {height}");
       Console.WriteLine($"Area: {CalculateArea()}");
   }
}

class Program 
{
     static void Main(string[] args)
     {
         // Circle 객체 생성 및 출력
         Circle circle = new Circle(5);
         circle.Display();

         // Rectangle 객체 생성 및 출력 
         Rectangle rectangle = new Rectangle(4, 6);
         rectangle.Display();
     }
}

IShape 인터페이스는 CalculateArea()와 Display()라는 두 가지 멤버 메서드를 선언한다. CircleRectangle클래스는 이러한 멤버 메서드를 구현하여 해당 계약을 충족시켜야 한다.
인터페이스는 다른 클래스들이 공유할 수 있는 일종의 계약이므로, 다른 형식들 사이에 공유 가능한 동작을 정의하기 위해 자주 사용된다.

2. 인터페이스 인스턴스 파라미터로 받기

인터페이스형의 인스턴스를 파라미터로 받는 경우, 다양한 클래스들이 동일한 인터페이스를 구현하므로 유연성확장성을 높일 수 있다.

예시는 아래와 같다.

// IPlayable 인터페이스 정의
public interface IPlayable
{
    void Play();
}

// AudioPlayer 클래스가 IPlayable 인터페이스를 구현함
public class AudioPlayer : IPlayable
{
    public void Play()
    {
        Console.WriteLine("Playing audio");
    }
}

// VideoPlayer 클래스가 IPlayable 인터페이스를 구현함
public class VideoPlayer : IPlayable
{
    public void Play()
    {
        Console.WriteLine("Playing video");
    }
}

// MediaPlayer 클래스에서 IPlayable 형식을 파라미터로 받는 메서드 정의
public class MediaPlayer
{
    public void StartPlayback(IPlayable playable)
    {
        playable.Play();
    }
}

class Program 
{
     static void Main(string[] args)
     {
         AudioPlayer audioPlayer = new AudioPlayer();
         VideoPlayer videoPlayer = new VideoPlayer();

         MediaPlayer mediaPlayer = new MediaPlayer();

         // StartPlayback 메서드에 다양한 형태의 객체 전달 가능 (다형성)
         mediaPlayer.StartPlayback(audioPlayer); // "Playing audio" 출력
         mediaPlayer.StartPlayback(videoPlayer); // "Playing video" 출력
     }
}

위 예시에서 IPlayable 인터페이스는 Play() 메서드만을 선언한다.

AudioPlayerVideoPlayer클래스는 이 인터페이스를 각각 구현하고, Play() 메서드를 재정의한다.
MediaPlayer 클래스에는 StartPlayback() 메서드가 있고, 이 메서드는 IPlayable 형식을 파라미터로 받는다. 전달된 객체에 대해 동일한 방식으로 재생 작업이 수행된다.

따라서, MediaPlayer 객체를 사용하여 다른 타입의 플레이어(AudioPlayer, VideoPLayer)들을 일관되게 처리할 수 있다. 이렇게 함으로써 코드 중복을 줄이고 유지 보수성과 확장성을 개선할 수 있다.


서비스 제공자 패턴(Service Provider Pattern): 인터페이스를 사용하여 특정 기능을 제공하는 서비스를 정의하고, 이를 구현한 여러 클래스들을 동적으로 교체하거나 선택할 수 있다. 이는 유연성과 확장성을 높이는 데 도움이 된다.

// ILogger 인터페이스 정의
public interface ILogger
{
    void Log(string message);
}

// FileLogger 클래스가 ILogger 인터페이스를 구현함
public class FileLogger : ILogger
{
    public void Log(string message)
    {
        // 파일에 로그 기록
    }
}

// DatabaseLogger 클래스가 ILogger 인터페이스를 구현함
public class DatabaseLogger : ILogger
{
    public void Log(string message)
    {
        // 데이터베이스에 로그 기록
    }
}

// LogManager 클래스에서 ILogger 형식을 사용하여 로깅 작업 수행
public class LogManager
{
    private readonly ILogger logger;

    public LogManager(ILogger logger)
    {
        this.logger = logger;
    }

    public void DoSomething()
    {
        // 작업 수행

        logger.Log("Something happened"); // 로그 작성

        // 추가 작업 수행
   }
}

class Program 
{
     static void Main(string[] args)
     {
         FileLogger fileLogger = new FileLogger();
         DatabaseLogger databaseLogger = new DatabaseLogger();

         LogManager logManager1 = new LogManager(fileLogger);
         logManager1.DoSomething(); // 파일에 로그 기록

         LogManager logManager2 = new LogManager(databaseLogger);
         logManager2.DoSomething(); // 데이터베이스에 로그 기록 
     }
}

위 예시에서 ILogger 인터페이스는 Log() 메서드를 선언한다.

FileLogger와 DatabaseLogger 클래스는 이 인터페이스를 각각 구현하고, Log() 메서드를 재정의하여 파일 또는 데이터베이스에 로그를 기록한다.

LogManager 클래스는 생성자로 ILogger 형식의 객체(여기서는 Filelogger 또는 Databaselogger)를 받아 해당 객체로부터 상황에 맞게 로깅 작업을 수행합니다.

이렇게 함으로써 다른 종류의 로깅 시나리오에 대해 유연하게 대응할 수 있습니다.

댓글남기기