25

SOLID やその他の設計原則について読んでいました。ISPは「実装ではなく、インターフェースへのプログラム」と同じだと思いました。しかし、これらは異なる原則のように見えますか?

違いはありますか?

4

6 に答える 6

45

Robert Martin は、彼の著書「UML for Java Programmers」で、インターフェイス分離の原則 (ISP) について非常によく説明しています。それに基づいて、ISP は、論理的で首尾一貫した 1 つのグループに「焦点を合わせた」インターフェイスに関するものではないと思います。なぜなら、それは言うまでもありません。または、少なくとも言うまでもありません。各クラス、インターフェース、または抽象クラスは、そのように設計する必要があります。

それで、ISPとは何ですか?例を挙げて説明しましょう。クラス A と、クラス A のクライアントであるクラス B があるとします。クラス A に 10 個のメソッドがあり、そのうちの 2 つだけが B によって使用されているとします。B は、A の 10 個のメソッドすべてについて知る必要がありますか? ? おそらくそうではありません - 情報隠蔽の原則。公開すればするほど、カップリングのチャンスが生まれます。そのため、2 つのクラスの間にインターフェース (C と呼ぶ) を挿入することができます (分離)。そのインターフェイスは、B によって使用される 2 つのメソッドのみを宣言し、B は A に直接依存するのではなく、そのインターフェイスに依存します。

だから今、

class A {
  method1()
  method2()
  // more methods
  method10()
}

class B {
   A a = new A()
}

となります

interface C {
  method1()
  method2()
}

class A implements C{
  method1()
  method2()
  // more methods
  method10()
}

class B {
  C c = new A()      
}   

これにより、B が必要以上に知ることを防ぎます。

于 2012-02-13T03:01:01.537 に答える
37

ISP は、個別のまとまりのある動作を表す各インターフェイスの概念に重点を置いています。

つまり、オブジェクトが行うべきことの各論理グループは、単一の特定のインターフェイスにマップされます。クラスはいくつかのことをしたいかもしれませんが、それぞれがその動作を表す特定のインターフェースにマップされます。アイデアは、各インターフェイスが非常に集中しているということです。

于 2012-02-12T15:13:24.270 に答える
16

多くのメソッドを実装する 1 つのファット インターフェイスがあるとします。

そのファット インターフェイスを実装するすべてのクラスは、これらすべてのメソッドの実装を提供する必要があります。一部のメソッドは、その具象クラスに適用できない場合があります。しかし、インターフェイス分離の原則がない場合でも、実装を提供する必要があります。

Interface segregationがない場合のコード例を見てみましょう。

interface Shape{
    public int getLength();
    public int getWidth();
    public int getRadius();
    public double getArea();
}

class Rectangle implements Shape{
    int length;
    int width;
    public Rectangle(int length, int width){
        this.length = length;
        this.width = width;
    }
    public int getLength(){
        return length;
    }
    public int getWidth(){
        return width;
    }
    public int getRadius(){
        // Not applicable
        return 0;
    }
    public double getArea(){
        return width * length;
    }
}
class Square implements Shape{
    int length;

    public Square(int length){
        this.length = length;
    }
    public int getLength(){
        return length;
    }
    public int getWidth(){
        // Not applicable
        return 0;
    }
    public int getRadius(){
        // Not applicable
        return 0;
    }
    public double getArea(){
        return length * length;
    }
}

class Circle implements Shape{
    int radius;
    public Circle(int radius){
        this.radius = radius;
    }
    public int getLength(){
        // Not applicable
        return 0;
    }
    public int getWidth(){
        // Not applicable
        return 0;
    }
    public int getRadius(){
        return radius;
    }
    public double getArea(){
        return 3.14* radius * radius;
    }
}

public class InterfaceNoSeggration{
    public static void main(String args[]){
        Rectangle r = new Rectangle(10,20);
        Square s = new Square(15);
        Circle c = new Circle(2);
        System.out.println("Rectangle area:"+r.getArea());
        System.out.println("Square area:"+s.getArea());
        System.out.println("Circle area:"+c.getArea());

    }
}

出力:

java InterfaceNoSeggration
Rectangle area:200.0
Square area:225.0
Circle area:12.56

ノート:

  1. Shape、 、などのすべてのShape実装に必要なメソッドを含む、汎用のファット インターフェイスです。ただし、それぞれの Shape チャイルドではいくつかのメソッドのみが必要ですRectangleCircleSquare

     Rectangle : getLength(), getWidth(), getArea()
     Square    : getLength() and getArea()
     Circle    : getRadius() and getArea()
    
  2. 分離がない場合、すべての Shape は Fat インターフェイス全体を実装しています: Shape.

次のようにコードを変更すると、インターフェース分離の原則で同じ出力を得ることができます。

interface Length{
    public int getLength();
}
interface Width{
    public int getWidth();
}
interface Radius{
    public int getRadius();
}
interface Area {
    public double getArea();
}


class Rectangle implements Length,Width,Area{
    int length;
    int width;
    public Rectangle(int length, int width){
        this.length = length;
        this.width = width;
    }
    public int getLength(){
        return length;
    }
    public int getWidth(){
        return width;
    }
    public int getRadius(){
        // Not applicable
        return 0;
    }
    public double getArea(){
        return width * length;
    }
}
class Square implements Length,Area{
    int length;

    public Square(int length){
        this.length = length;
    }
    public int getLength(){
        return length;
    }
    public int getWidth(){
        // Not applicable
        return 0;
    }
    public int getRadius(){
        // Not applicable
        return 0;
    }
    public double getArea(){
        return length * length;
    }
}

class Circle implements Radius,Area{
    int radius;
    public Circle(int radius){
        this.radius = radius;
    }
    public int getLength(){
        // Not applicable
        return 0;
    }
    public int getWidth(){
        // Not applicable
        return 0;
    }
    public int getRadius(){
        return radius;
    }
    public double getArea(){
        return 3.14* radius * radius;
    }
}

public class InterfaceSeggration{
    public static void main(String args[]){
        Rectangle r = new Rectangle(10,20);
        Square s = new Square(15);
        Circle c = new Circle(2);
        System.out.println("Rectangle area:"+r.getArea());
        System.out.println("Square area:"+s.getArea());
        System.out.println("Circle area:"+c.getArea());

    }
}

ノート:

のような個々のシェイプはRectangle、必要なインターフェイスのみSquareCircle実装し、未使用のメソッドを取り除きました。

于 2016-02-13T16:16:56.890 に答える
1
  1. IWorker インターフェイス:

    public interface IWorker {
        public void work();
        public void eat();
    
    }
    
  2. 開発者クラス:

    public class Developer implements IWorker {
    
         @Override
         public void work() {
               // TODO Auto-generated method stub
               System.out.println("Developer working");
    
         }
    
         @Override
         public void eat() {
               // TODO Auto-generated method stub
               System.out.println("developer eating");
    
         }
    
    }
    
  3. ロボットクラス:

    public class Robot implements IWorker {
    
         @Override
         public void work() {
               // TODO Auto-generated method stub
               System.out.println("robot is working");
    
         }
    
         @Override
         public void eat() {
               // TODO Auto-generated method stub
               throw new UnsupportedOperationException("cannot eat");
    
         }
    
    }
    

より完全な例については、こちらを参照してください

于 2017-06-20T17:58:41.580 に答える