はじめに
オブジェクト指向設計で出てくる「関心の分離」「依存性の注入」「生成パターン」の関係性を整理します。
この3つの考え方は密接に関連していて、特にクラス設計やインスタンス生成の場面で重要な役割を果たします。
この記事では、それらのつながりと背景、そしてなぜそれが必要になるのかを、整理してみました。
関心の分離とは?
「関心の分離」とは、1つのクラスは1つの責任に集中すべきという原則。
たとえば、以下のような状況。
- クラスAの中で、クラスBやクラスCなどの依存オブジェクトを自分でnewしている
- 外からみると、クラスAの依存先がわかりにくい
- 将来、依存オブジェクトの構成や設定が変わると、Aの実装まで変更が必要になる
こうした「作る」と「使う」が混在している状態は、柔軟性が低く、修正やテストに弱い構造。
依存性の注入(DI)とは?
そこで登場するのが依存性の注入(DI)。
クラスが必要なオブジェクト(依存)を、自分で作らずに外から渡してもらう設計方法。特に「状態としてクラス内で保持して何度も使うような依存」に対して使われる。
例:
class UserController {
private UserService $service;
public function __construct(UserService $service) {
$this->service = $service;
}
public function store(Request $request) {
// UserService を使ってユーザーを登録する
$this->service->createUser($request);
}
}
UserController は UserService を「使う」けれど「作る」責任は持たない。
メリット
- 使うクラスが「作り方」から解放される(関心の分離)
- テスト時に依存をモックなどに差し替えられる
- 依存オブジェクトの作り方が変わっても、使う側を修正しなくてよい
デメリット
- 呼び出し元が依存をすべて組み立てる必要があり、複雑になることがある。
生成パターンとは?
依存性の注入を使うことで、クラス同士の結びつきはゆるくできるが、
代わりに「その依存オブジェクトをどう作るか?」という新しい問題が生まれる。
たとえば、UserService を使いたいときに、UserRepository や Logger を先に用意する必要があり、さらに UserRepository の内部でも DB接続などの依存がある場合、その「作る処理」自体が複雑になってしまいます。
その問題を解決するために使われるのが、生成パターン(Factory や Builder など) 。
目的
- 複雑な生成処理を別クラスに切り出して管理する
- 作り方が変わっても、使う側のコードはそのまま
例:
class UserServiceFactory {
public static function create(): UserService {
$config = new Config(...);
$db = new DatabaseConnection($config);
$repo = new UserRepository($db);
$logger = new Logger();
return new UserService($repo, $logger);
}
}