DIPについて学ぶ
DIPとは
SOLID原則のD
Dependency inversion principle
日本語で依存性逆転の法則
基本的に子クラスは親クラスに依存してるが、これを逆転させる考え
どう逆転させるかというと、抽象クラスを利用する。インタフェースだね。
code:java
public interface MessageSender {
void send(String message);
}
public class EmailSender implements MessageSender {
public void send(String message) { System.out.println("メール送信: " + message); }
}
public class NotificationService {
private final MessageSender sender;
public NotificationService(MessageSender sender) {
this.sender = sender;
}
public void send(String message) {
sender.send(message);
}
}
普通に考えるとNotificationServiceとEmailSenderだけを実装しがちだけど、
MessageSenderインタフェースを使うことで、
EmailSenderが依存しているものはMessageSender
NotificationServiceが依存しているものもMessangeSender
になって依存性の逆転が起きる
https://scrapbox.io/files/690085b7167712f96bf202ea.png
使う場合はこう
code:main.java
public class Main {
public static void main(String[] args) {
MessageSender sender = new EmailSender();
NotificationService service = new NotificationService(sender);
service.send("こんにちは!");
}
}
たとえば、別の送信方法が見つかった場合はこのように実装する
code:ChatSender.java
public class ChatSender implements MessageSender {
public void send(String message) { System.out.println("チャット送信: " + message); }
}
code:main.java
public class Main {
public static void main(String[] args) {
MessageSender sender = new ChatSender();
NotificationService service = new NotificationService(sender);
service.send("こんにちは!");
}
}
変更箇所が少なくなり、保守性が向上する。
おそらく、DDD設計で重要な要素となるので覚えておく。
DIを手動で注入する
code:manual.java
MessageSender sender = new EmailSender();
NotificationService service = new NotificationService(sender);
SpringBootの場合は別の書き方になる。
code:spring.java
public interface MessageSender {
void send(String message);
}
@Component
public class EmailSender implements MessageSender {
@Override
public void send(String message) {
System.out.println("メール送信: " + message);
}
}
@Service
public class NotificationService {
private final MessageSender sender;
public NotificationService(MessageSender sender) {
this.sender = sender;
}
public void send(String message) {
sender.send(message);
}
}
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
// 起動時直後に実行する機能
@Bean
CommandLineRunner run(NotificationService service) {
return args -> {
service.send("こんにちは");
};
}
}