2012-02-12 4 views

답변

26

ISP는 하나의 개별적이고 응집력있는 행동을 나타내는 각 인터페이스의 개념에 중점을 둡니다.

즉, 개체가 수행해야하는 논리적 인 각 그룹은 단일 특정 인터페이스에 매핑됩니다. 클래스는 여러 가지 작업을 수행하려고 할 수 있지만 각 작업은 해당 동작을 나타내는 특정 인터페이스에 매핑됩니다. 아이디어는 각 인터페이스가 매우 집중되어 있습니다.

+1

짧고 지점에 – Gordon

+1

와우 .. 감사합니다! 캔트 다른 5 분 동의 : – hangar18

+3

+1. 이 원리를 따르지 않는다는 것을 알려주는 고전적인 "냄새"는 클라이언트가 인터페이스의 메소드 중 일부만 호출하는 인터페이스를 사용하는 경우에 따라 달라집니다. – TrueWill

32

로버트 마틴 (Robert Martin)은 "Java 프로그래머 용 UML"이라는 책에서 인터페이스 분리 원리 (Interface Separation Principle, ISP)에 대해 매우 잘 설명하고 있습니다. 이를 바탕으로, 나는 ISP가 하나의 논리적이고 일관된 일들에 초점을 맞추고 있다고 생각하지 않는다. 왜냐하면, 그것은 말도하지 않습니다. 또는, 적어도 그것은 말없이 가야한다. 각 클래스, 인터페이스 또는 추상 클래스는 그렇게 설계되어야합니다.

ISP는 무엇입니까? 예를 들어 설명해 드리겠습니다. 클래스 A는 클래스 A의 클라이언트이고 클래스 B는 클래스 A의 클라이언트입니다. 클래스 A에는 10 개의 메소드가 있으며 그 중 두 개만 B에서 사용합니다. 이제 B는 A의 10 가지 메소드 모두에 대해 알아야합니다. ? 아마 정보 숨기기의 원칙이 아닙니다. 더 많이 노출할수록 더 많은 커플 링 기회를 창출 할 수 있습니다. 따라서 두 클래스 (분리) 사이에 인터페이스를 삽입 할 수 있습니다 (C).

class A { 
    method1() 
    method2() 
    // more methods 
    method10() 
} 
class B { 
    A a = new A() 

} 

가 될 것이며,이 인터페이스는 단지 B에 의해 사용되는 두 가지 방법을 선언하는 것이고, B는 이제

A.

직접 대신, 그 인터페이스에 의존 할 것이다

interface C { 
     method1() 
     method2() 
} 



class A implements C{ 
     method1() 
     method2() 
     // more methods 
     method10() 
    } 
    class B { 
     C c = new A() 

} 

이것은 B가해야하는 것 이상을 알 수 없도록합니다.

+0

자세한 설명을 위해 시간을내어 +1하십시오! – hangar18

+0

우수 답변! –

+1

@ Pete Stensønes 설명은 내가 한 것보다 더 일반적이고 정확합니다. 나는 그의 정의에 더 많은 관심을 기울일 것을 사람들에게 제안한다. 내 잘못은 아니지만 그 개념을 한 가지 유스 케이스로 설명하며 일반적인 포인트를 놓치고 있습니다. –

1

위의 두 대답 모두에 동의하십시오. 여기에 (PHP에서)이 원칙의 실제 예입니다

@Override 
public void foo() { 
    //Not used: just needed to implement interface 
} 
+0

특히 컬렉션에서만 NotImplementedException을 throw하는 Java API 클래스와 비교하십시오. Moderation에서는 인터페이스에서 부분적으로 사용되는 메소드에 유용 할 수 있지만 MutableMap을 사용하여 Map을 확장하는 것이 대안 일 수 있습니다. – hexafraction

0

문제 : 그냥, 당신은 자신이 일을 찾을해야 위의 TrueWill의 코드 냄새의 예를 제공합니다 성명서 :

다양한 형태의 콘텐츠에 의견/토론이 필요합니다. 이 내용은 포럼 주제에서 뉴스 기사, 사용자 프로필, 대화 형식의 개인 메시지에 이르기까지 다양합니다.

우리는 주어진 콘텐츠 엔티티에 Discussion를 첨부 재사용 가능한 DiscussionManager 클래스를 원할 것입니다

아키텍처. 그러나 위의 네 가지 예 (및 그 이상)는 개념적으로 모두 다릅니다. 만약 우리가 DiscussionManager에서 그것들을 사용하기를 원한다면, 네 + 모든 것이 모두 공유하는 하나의 공용 인터페이스를 가질 필요가 있습니다. 인수가 누출되지 않도록하려는 경우 (예 : 유형 확인 없음)를 제외하고는 DiscussionManager에서 사용할 수있는 다른 방법은 없습니다.

해결 방법 : 이러한 방법으로 Discussable 인터페이스 :

  • attachDiscussion($topic_id)
  • detachDiscussion()
  • getDiscussionID() 다음 DiscussionManager

은 다음과 같습니다

class DiscussionManager 
{ 
    public function addDiscussionToContent(Discussable $Content) 
    { 
     $Discussion = $this->DiscussionFactory->make(...some data...); 
     $Discussion->save() // Or $this->DiscussionRepository->save($Discussion); 
     $Content->attachDiscussion($Discussion->getID()); // Maybe saves itself, or you can save through a repository 
    } 

    public function deleteDiscussion(Discussable $Content) 
    { 
     $id = $Content->getDiscussionID(); 
     $Content->detatchDiscussion(); 
     $this->DiscussionRepository->delete($id); 
    } 

    public function closeDiscussion($discussion_id) { ... } 
} 

이렇게하면 DiscussionManager은 사용하는 다양한 콘텐츠 형식과 관련이없는 동작을 전혀 신경 쓰지 않습니다. 그것은 오직 그 행동이 관련된 것과 관계없이 그들이 필요로하는 행동에만 관심이 있습니다. 따라서 토론 할 내용 유형 인 Discussable 인터페이스를 제공하여 인터페이스 분리 원리를 사용하고 있습니다.

이것은 추상 기본 클래스가 좋은 생각이 아닌 상황의 좋은 예입니다. 포럼 주제, 사용자 프로필 및 뉴스 기사는 원격 개념적으로 똑같은 것이 아니기 때문에 토론 행동을 상속 받도록하려고하면 관련없는 부모와 이상하게 연결됩니다. 토론을 나타내는 특정 인터페이스를 사용하여 토론하려는 엔티티가 해당 토론을 관리 할 클라이언트 코드와 호환되는지 확인할 수 있습니다.

이 예제는 PHP의 특성을 사용하기에 좋은 후보가 될 수 있습니다.

7

구현할 많은 메소드가있는 하나의 뚱뚱한 인터페이스가 있다고 가정하십시오.

뚱뚱한 공용 영역을 실행하는 어떤 종류는이 모든 방법을위한 실시를 제공해야한다. 일부 방법은 해당 구체적인 클래스에 적용되지 않을 수 있습니다. 그러나 여전히 인터페이스 분리 원칙이없는 구현을 제공해야합니다.

에 예제 코드를 살펴보고 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. ShapeRectangle, CircleSquare 같은 모든 Shape 구현에 필요한 방법을 포함하는 범용 지방 인터페이스입니다. 그러나 일부 방법은 각각의 모양에 필요한 분리의 부재에서

    Rectangle : getLength(), getWidth(), getArea() 
    Square : getLength() and getArea() 
    Circle : getRadius() and getArea() 
    
  2. 차일, 모든 모양은 전체 지방 인터페이스를 구현 한 : 모양. 우리는 다음과 같은 코드를 변경하는 경우

우리는 인터페이스 분리의 원칙과 같은 결과를 얻을 수 있습니다.

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 같은

이제 각각의 모양은 필요한 인터페이스를 구현하고 않은 사용 방법 제거되었다.

+0

나는 이것에 -1 표를 던졌지 만 실제로 실수였다. 나는이 대답을 좋아한다 : D –

+0

나는 의견이 적힌 투표에 대해 놀랐다. 시스템에서 허용하는 경우 수정할 수 있습니다. 그렇지 않으면 당신은 24 시간 후에 와야합니다 :) –

+0

나는이 메시지를 가지고 있습니다 : ""당신은 마지막으로이 답변에 3 시간 전에 투표했습니다. 이 답변을 편집하지 않으면 투표가 잠겨 있습니다. ""따라서 메시지를 업데이트해야합니다.하지만 24 시간 내에 방문 할 수 있다면이 하향 투표를 삭제하겠습니다 : D –

0
  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"); 
    
        } 
    
    } 
    

보다 완전한 예를 보려면 here으로 가십시오.

관련 문제