DIP(The Dependency Inversion Principle)依存性反転の原則
– 抽象に依存すべき。具象クラスに依存してはいけない。
HeadFirstデザインパターンの説明が分かりやすかったです。
↑では様々な種類のPizza(NYCheesePizza,NYClamPizza…)を作るPizzaStoreを例に出しています🍕🍕🍕
[Before]なにも考えず実装する🙄
PizzaStoreは具象クラスであるNYCheesePizzaやNYClamPizzaに依存しています。
高水準なクラス PizzaStoreから低水準なクラスNYCheesePizzaに依存する形となり、依存の方向は上から下(矢印)になっています。
デメリット🙅♂️
PizzaStoreは4つの具象クラス依存しており、Pizzaの種類が増えるとさらに依存する具象クラスが増え、コードの修正も必要となってしまいます。
[After]DIPに沿った実装をする🤔
抽象クラスPizzaを追加しました。
PizzaStoreは抽象クラスPizzaを作成し、抽象クラスPizzaに依存するようになります。
また、具象クラスだったNYCheesePizzaやNYClamPizzaは抽象クラスPizzaを実装するようになり、抽象クラスPizzaに依存するようになりました。
これにより、原則通りにPizzaStoreもNYCheesePizzaやNYClamPizzaもすべて抽象に依存するようになりました!!!
さらに、依存の方向を示す矢印も上から下だったものが「反転」して、下から上への依存となりました💡
メリット🙆♂️
PizzaStoreは具体的なPizzaの種類を知らなくていい(抽象Pizzaクラスしか知らない)ので、新しい具象Pizzaクラスが作成されても修正は少なくなります。
まとめ
この原則に従った設計を考える時には、高水準コンポーネントではなく低水準コンポーネントから抽象化できないかを考えていくといい気がしました。
また、この原則に従うための指針として
- 具象クラスへの参照を保持する変数を持たない
- 具象クラスからクラスを継承しない
- ベースクラスの実装済みメソッドをオーバーライドしない
というのも大事だなと改めて感じました。