자바에는 추상클래스와 인터페이스이 존재한다.

이 둘은 객체지향적인 특성을 더해준다고 한다.

이제 자바를 시작하는 입장에서는 바로 와닿는 개념이 아니라 먼저 정리해보고

더 배워보면 언젠간 무릎을 탁 치는 순간이 오길 바란다.


인터페이스의 효과

느슨한 결합

결합도란 구성 요소 간의 의존성을 의미한다.

어디에 의존 한다는 건 그 요소가 변경되었을 경우 자기도 변경 되어야 한다는 의미이다.

인터페이스는 결합도를 낮출 수 있다.

interface Payment {
    void processPayment();
}

class CreditCardPayment implements Payment {
    @Override
    public void processPayment() {
        System.out.println("Processing credit card payment");
    }
}

class PaypalPayment implements Payment {
    @Override
    public void processPayment() {
        System.out.println("Processing PayPal payment");
    }
}

class PaymentService {
    private Payment payment;

    public PaymentService(Payment payment) {
        this.payment = payment;
    }

    public void makePayment() {
        payment.processPayment();
    }
}

 

여기서 PaymentService는 Payment에 의존한다.

하지만 그 Payment를 구현한 구현체들이 어떻게 구현 됐는지는 알 필요 없이 사용가능하다.

그 구현체가 변경되어도 PaymentService의 코드는 바꿀 필요가 없으니 의존성이 없다는 것


다형성

다형성은 객체지향에서 매우 중요한 개념이라고 한다.

부모 클래스나 인터페이스를 통해 하위 클래스들을 다룰 수 있는 걸 의미한다.

class Main {
    public static void main(String[] args) {
        Payment payment1 = new CreditCardPayment();
        Payment payment2 = new PaypalPayment();

        payment1.processPayment(); // Processing credit card payment
        payment2.processPayment(); // Processing PayPal payment
    }
}

상위 인터페이스인 Payment로 하위클래스 CreditCardPayment와 PaypalPayment를 모두 사용할 수 있다.


의존성 주입

의존성을 외부에서 주입해주는 것

  1. 생성자 주입(Constructor Injection): 의존성을 생성자의 매개변수로 전달받아 주입하는 방식.
  2. 세터 주입(Setter Injection): 의존성을 세터 메서드를 통해 주입하는 방식.
  3. 필드 주입(Field Injection): 의존성을 직접 필드에 주입하는 방식 (주로 프레임워크에서 사용)

이렇게 세 방법이 있다.

 

생성자 주입

interface MessageService {
    void sendMessage(String message);
}

class EmailService implements MessageService {
    @Override
    public void sendMessage(String message) {
        System.out.println("Sending email: " + message);
    }
}

class SMSService implements MessageService {
    @Override
    public void sendMessage(String message) {
        System.out.println("Sending SMS: " + message);
    }
}

class NotificationService {
    private MessageService messageService;

    public NotificationService(MessageService messageService) {
        this.messageService = messageService;
    }

    public void notify(String message) {
        messageService.sendMessage(message);
    }
}

public class Main {
    public static void main(String[] args) {
        MessageService emailService = new EmailService();
        NotificationService notificationService = new NotificationService(emailService);
        notificationService.notify("Hello, world!");  // "Sending email: Hello, world!"

        MessageService smsService = new SMSService();
        notificationService = new NotificationService(smsService);
        notificationService.notify("Hello, world!");  // "Sending SMS: Hello, world!"
    }
}

 

NotificationService는 생성자에 의존할 코드를 주입받는다.

 

세터 주입

    public void setMessageService(MessageService messageService) {
        this.messageService = messageService;
    }
    
    notificationService.setMessageService(emailService);

이렇게 생성자에서 주입하지 않고 세터로 주입 할 수도 있다.

 

필드 주입은 스프링 배울 때 다시 포스팅 해야겠다.


'공부일지 > Java' 카테고리의 다른 글

[JAVA] String, StringBuffer, StringBuilder  (0) 2024.07.01
[JAVA] 6/21에 배운 것  (0) 2024.06.26
[JAVA] 6/20 배운거 클래스  (0) 2024.06.20
[JAVA] 추상클래스와 인터페이스  (0) 2024.06.19
[JAVA] Wrapper Class  (0) 2024.06.18

+ Recent posts