インターフェイス分離の原則は、単一責任の原則の代わりにすぎませんか?
クラスが SRP を満たす場合、複数のインターフェイスを抽出する必要はないと思います。
したがって、ISP は、何らかの理由で SRP を壊さなければならない場合の解決策のように見えます。
私は正しいですか?
インターフェイス分離の原則は、単一責任の原則の代わりにすぎませんか?
クラスが SRP を満たす場合、複数のインターフェイスを抽出する必要はないと思います。
したがって、ISP は、何らかの理由で SRP を壊さなければならない場合の解決策のように見えます。
私は正しいですか?
いいえ。ハードドライブなどにデータを永続化する役割を持つクラスの例を考えてみましょう。クラスを読み取り部分と書き込み部分に分割しても、実際には意味がありません。ただし、クラスをデータの読み取りのみに使用するクライアント、データの書き込みのみに使用するクライアント、および両方を行うクライアントがあります。ここで 3 つの異なるインターフェイスを使用して ISP を適用すると、優れたソリューションになります。
クラスが SRP を満たす場合、複数のインターフェイスを抽出する必要はないと思います。
単一責任の原則とは、クラス (またはメソッド) に複数の変更理由があってはならないというものです (つまり、それぞれが 1 つの機能のみを担当します)。これを尊重するために、システムの開発に合わせて新しいクラスを作成する必要があります。
たとえば、Car
クラスから始めて、ギアを変更する機能が必要であることがわかった場合、これをGearbox
クラスに抽出します。これは、ギア チェンジの背後にあるメカニズムを変更しても、親Car
クラスを変更する必要がないことを意味します。車にパワー ステアリングを追加する場合は、これを独自のクラスに再度抽出します。ラジオは別のクラスになります。
この抽象化のカスケードは、Car
クラス全体で発生します。それ自体から下に移動するとCar
、各クラスで詳細が増加することがわかります。たとえば、Car
クラスにはchangeGear()
、ユーザーがギアを選択できるようにするメソッドがある場合がありますが、Gearbox
クラスは作成の核心に注意を払います。これが発生します (例: クラッチを踏む、現在のギアを外す、新しいギアを選択するなど)。
ただし、OO 設計ではGearbox
、エンドユーザーに詳細を公開したくありません。内部がどのように機能するかを知る必要なく、高いレベルの抽象化でシステムとやり取りしてもらいたいのです。また、ユーザーがコードをリファクタリングしなくても将来的に変更できるように、これらの内部をリングフェンスしたいと考えています (これが、private
またはとしてフラグを立てる理由protected
です)。
Car
このため、ユーザーがクラス自体を介してのみ車と対話できるようにします。ここで、インターフェイス分離の原則の出番です。SRP は、クラスがそのサブコンポーネントを別のクラスに委譲することを保証しますが、すべてのメソッドはクラス自体を通じて呼び出されます。ISPは、これらすべてを 1 つのインターフェイスにまとめるのではなく、論理的な区別を作成し、関連する機能のために複数のインターフェイスを公開することを保証します。Car
public
Car
いいえ。
クラスは複数のインターフェイスを実装できますが、クラスにのみ適用可能なメソッドを実装する必要があります。
のような 10 以上の異なる機能があるとしますClimb, Think, Learn, Apply
。クラスDog
は 2 つの機能を持つCat
ことができ、クラスは 2 つの機能を持つことができ、クラスMan
は 6 つの機能を持つことができます。それぞれのクラスで適用可能な機能のみを実装することは理にかなっています。
このコードを見てください。
public class ISRDemo{
public static void main(String args[]){
Dog dog = new Dog("Jack",16);
System.out.println(dog);
Learn dl = dog;
dl.learn();
ProtectOwner p = dog;
p.protectOwner();
Cat cat = new Cat("Joe",20);
System.out.println(cat);
Climb c = cat;
c.climb();
Remember r = cat;
cat.doRemember();
Man man = new Man("Ravindra",40);
System.out.println(man);
Think t = man;
t.think();
Learn l = man;
l.learn();
Apply a = man;
a.apply();
PlaySports pm = man;
pm.playSports();
Remember rm = man;
rm.doRemember();
}
}
class Dog implements Learn,ProtectOwner{
private String name;
private int age;
public Dog(String name,int age){
this.name = name;
this.age = age;
}
public void learn(){
System.out.println(this.getClass().getSimpleName()+ " can learn");
}
public void protectOwner(){
System.out.println(this.getClass().getSimpleName()+ " can protect owner");
}
public String toString(){
return "Dog :"+name+":Age:"+age;
}
}
class Cat implements Climb,Remember {
private String name;
private int age;
public Cat(String name,int age){
this.name = name;
this.age = age;
}
public void climb(){
System.out.println(this.getClass().getSimpleName()+ " can climb");
}
public void doRemember(){
System.out.println(this.getClass().getSimpleName()+ " can remember");
}
public String toString(){
return "Cat :"+name+":Age:"+age;
}
}
interface ProtectOwner {
public void protectOwner();
}
interface Remember{
public void doRemember();
}
interface Climb{
public void climb();
}
interface Think {
public void think();
}
interface Learn {
public void learn();
}
interface Apply{
public void apply();
}
interface PlaySports{
public void playSports();
}
class Man implements Think,Learn,Apply,PlaySports,Remember{
String name;
int age;
public Man(String name,int age){
this.name = name;
this.age = age;
}
public void think(){
System.out.println(this.getClass().getSimpleName() + " can think");
}
public void learn(){
System.out.println(this.getClass().getSimpleName() + " can learn");
}
public void apply(){
System.out.println(this.getClass().getSimpleName() + " can apply");
}
public void playSports(){
System.out.println(this.getClass().getSimpleName() + " can play sports");
}
public void doRemember(){
System.out.println(this.getClass().getSimpleName() + " can remember");
}
public String toString(){
return "Man :"+name+":Age:"+age;
}
}
出力:
java ISRDemo
Dog :Jack:Age:16
Dog can learn
Dog can protect owner
Cat :Joe:Age:20
Cat can climb
Cat can remember
Man :Ravindra:Age:40
Man can think
Man can learn
Man can apply
Man can play sports
Man can remember
上記の例では、インターフェイスの分離により、すべての機能をファット インターフェイスで宣言するのではなく、10 個のインターフェイスで 10 個の機能を定義することが推奨されます。ただし、単一の責任基準を満たすために異なるクラスが必要であるという意味ではありません。
Dog, Cat and Man
同じ例のクラスの実装を見てください。