SRP
Single Responsibilty Principle
→ 1クラス1責任
疑問点
責任っていう表現は曖昧で、どのようにこの原則を守れているかを判断できるのか?
変更がある時、他のクラスまで影響が少ないと「1クラス1責任」がうまく守られていると言える
OCP ⭐️⭐️
Open-Closed Principle
→ 既存コードを変更せず、拡張できること。(多態性)
疑問点1
どうしても多態性を守って設計しても、ピュアJAVAではオブジェクトを生成する時、コードの変更が必要になるのでは??
//既存クライアントコード
ParentClass a = new Child1Class();
a.method1();
...
//拡張後
ParentClass a = new Child2Class();//どうしても生成部分は修正する必要が出てくる
a.method1();//この部分は変更不要
...
別途オブジェクト生成者が必要になる。→SPRINGコンテナー(DI、IOCコンテナー)がその役割をする。
疑問点2
え、ではピュアJAVAではOCP守れないの??
OCPを守れないケースは多く存在する。
例えば予測できる例外もOCPに違反する。
メソッドで予測できる例外を投げた時、catch blockが何段階か上にあるとしたら、上位メソッドまで連鎖的に修正が必要になる。(みんな経験あるはず…)
なので設計時はメリデメをよく判断して使用すること。
LSP
Liskov Substitution Principle
→ 親クラスの契約(規約)を守ること
コンパイルの成功失敗の問題ではない。
自動車インタフェースを継承して新しい自動車モデルクラスを作る時に、
自動車インタフェースにあるgoメソッドを
新しい自動車モデルクラスでオーバーライドして、
速度が下がるように実装してはいけない。
補足
難しい言葉で言うと親クラスの行動規範を子クラスが違反してはいけないということ
ISP
Interface Segregation Principle
→ 複数のインターフェースが汎用インターフェース1個より良い
DIP⭐️
Dependency Inversion Principle
→ 依存性逆転の原則
プログラマーは抽象化に依存するべき。具体化に依存してはいけない。
つまり、クラスに依存せず、インターフェースに依存すること。
疑問点
以下のケースの場合、SampleServiceはParentInterfaceとChild1Classの両方に依存しているのでは?
public class SampleService{
ParentInterface a = new Child1Class();
...
}
実際に両方へ依存しているため、その認識は正しい、上記のケースはDIPに違反してる
OCPと同じく…
別途オブジェクト生成者が必要になる。→SPRINGコンテナ(DI、IOCコンテナ)がその役割をする。
結論
オブジェクト指向設計の核心は多態性。
しかし多態性だけではOCPやDIPと守れないケースが存在する。
SPRINGの場合、DIコンテナがあり、クライアントコードの変更なしで機能を拡張できるようになる。