2009-10-16 6 views
9

이 복합의 잎 그는 결코 (인터페이스 분리의 위반)를 사용하려고하지 않습니다 추가 제거 및 GetChild 방법이있는 구성 요소를 구현복합 패턴은 솔리드입니까?

때문에 복합 패턴 SOLID의 사용인가? 복합 http://www.dofactory.com/Patterns/PatternComposite.aspx

+0

질문이 명확하지 않습니다. 또한, "솔리드"란 무엇을 의미합니까 – monksy

+0

위의 질문자를위한 솔리드 링크를 추가했습니다. – SingleShot

+0

SRP 및 LSP도 ISP와 함께 위반됩니다. SOLID는 위험합니다. :) – Narek

답변

10

당신의 연결 대부분의 책에 도시 된 바와 같이 패턴 진짜 냄새

링크 ComponentComposite의 방법을 가지고 있다는 것입니다. 패턴이 상당히 오래되어서 수년간 그런 식으로 반복 되었기 때문일 것으로 생각합니다. 제 생각에는 Composite에만 합성과 관련된 메소드가 있어야한다는 것입니다.

는 예전에 컴퓨터 게임을 통해 보드 게임을 변환. 그 놀이 피스는 육각형으로 나뉘어 진 지구의지도에 놓였습니다. 모든 육각형 중 99 %가 단일 위치를 나타냅니다. 불행히도 육각형 중 몇 개는 여러 위치를 포함하고 있습니다. 예를 들어 일부는 내부에 몇 개의 섬이 있습니다. 이러한 위치를 나타내는데 복합 패턴을 사용했지만 링크에는 묘사되지 않았습니다. 그것은 (자바)이 같은했다 다음 Composite이 합성 방법이 있습니다 만, 심지어는이 예에서 (대부분의 고객에게 아이가 있다는 사실을 노출하지 않습니다

public interface Location { 
    Set<Army> getArmies(); 
} 

public class SingleLocation implements Location { 

    public Set<Army> getArmies() { 
     return armies ; 
    } 

    private Set<Army> armies = new HashSet<Army>(); 
} 

public class CompositeLocation implements Location { 

    public Set<Army> getArmies() { 

     Set<Army> armies = new HashSet<Army>(); 

     for(Location subLocation: subLocations) { 
     armies.addAll(subLocation.getArmies()); 
     } 

     return armies; 
    } 

    public void addSubLocation(Location location) { 
     subLocations.add(location); 
    } 

    private Set<Location> subLocations = new HashSet<Location>(); 
} 

주, 클라이언트는 원하는 한 위치의 군대 목록 - 많은 하위 위치에 있다는 사실은 부적합합니다.

는 설정에 돌되지 않습니다 정확하게 구현해야하는 일을 마음 디자인 패턴하십시오. 그들을 조리법으로 생각하십시오. 요리하는 동안 조리법을 따라 가면 확실히 정확하게 따라갈 수 있습니다. 그러나 일부 요리사는 조리법에 자신의 단서를 던질 것입니다. 다른 사람들은 심지어 전문가이기 때문에 심지어 그것을 보지도 않고 조리법의 정신으로 무엇인가를 던질 수 있기 때문에 심지어 그것을 보지 않을 것입니다. 디자인 패턴에서도 마찬가지입니다. 그들은 전성있는 요리법입니다.

당신은 또한 그 고체 원리를 너무 멀리 가져갈 수 있습니다. 로버트 마틴 (Robert Martin)의 기사를 읽었을 때 그는 아무 생각없이 원칙을 적용하면 지나치게 복잡한 코드를 산출 할 것이라고 말합니다. 소프트웨어는 일련의 트레이드 오프 및 밸런싱을 통해 설계되었습니다. 때로는 순수 솔리드를 사용하지 않아도되므로 코드가 덜 복잡해집니다. 코드를 완벽하게 캡슐화하고 융통성있게 분리해야한다면 다음과 같은 새로운 프로그래밍 언어를 발명했을 것입니다 .-)

+0

좋은 이유가 있지만 매우 일반적입니다.하지만 표준 버전에는 이유가 있습니다. 예를 들어, 항목은 간단한 합성 이외에도 기능상의 종속성을 가질 수 있습니다. 예를 들어 단락의 높이는 줄 내의 각 문자의 높이에 따라 각 텍스트 줄의 높이에 따라 달라집니다. 별도의 해시를 사용하면 합성 된 항목은 해당 친척을 찾기 위해 합성을 다시 참조해야합니다. 물론 이것에도 장점이 있습니다. 복합 요소는 단락 높이와 같은 하위 트리 요약에 대한 책임을 질 수 있습니다. – Steve314

5

귀하의 링크에 설명 된 복합 패턴은 Liskov substitution principle 다섯 SOLID 원칙.

ComponentComposite 예에 대한 이해를 갖는 방법 Add(). LeafComponent에서 상속되므로 다른 Component처럼 Add() 메서드가 있습니다. 그러나 Leafs 아이를 가지고 있지 않기 때문에 다음과 같은 메소드 호출은 의미있는 결과를 반환 할 수 없습니다 :

myLeaf.Add(someChild);

은 그 호출이 추가 호출자에게 다른 방법으로 null을 반환하거나 표시하는 MethodNotSupportedException 던질 것을 Leaf에 아이는 말이되지 않습니다.

따라서 Leaf은 다른 Component과 같이 취급 할 수 없으므로 예외가 발생할 수 있습니다.Liskov substition 원리 상태 :

S는 하위 유형이다 Q (x)는 T 형식 다음 Q (Y)의 객체 X에 관한 증명 속성 타입 S의 객체 y를위한 진정한해야하자 T.

Components에는 자녀를 추가 할 수 있다는 속성이 있습니다. 그러나 LeafComponent의 하위 유형인데도 원칙을 위반하더라도 자녀를 Leaf에 추가 할 수 없습니다.

+0

유형이 Liskov 대체 원칙 위반으로 간주되기 위해 유형이 상위 유형과의 의미 상 상호 운용성에서 벗어나야하므로 리프 유형이 그렇다면 하위가있는 Add()를 호출하고이어서 호출 할 수 없기 때문입니다 예상되는 인덱스를 가진 GetChild(). 그러나 행위를 단순히 생략하는 것은 위반 행위가 될 수 없습니다. Add() 메서드에는 자식이 추가되었다는 피드백을 제공해야한다는 암시 적 또는 명시 적 계약이 없지만 추가 된 자식을 GetChild() 메서드로 검색 할 수 있다고 가정하는 암시 적 계약이 있습니다. –

+0

BTW, Null Object 패턴이 효과적인 이유는 의미 론적 상호 운용성을 유지하면서 동작을 생략하기 때문입니다. –

0

Composite를 사용하면 모든 객체를 균일하게 처리 할 수 ​​있으며 코드 냄새의 명확한 표시 인 "instanceOf"를 제거 할 수 있습니다. 언뜻보기에 LSP (Liskov 's)를 존중합니다. 그러나 일반적인 메소드 구현을 차별화하면 LSP를 위반하기 시작할 수 있습니다. 그래서, IMO, 우리는 균형을 유지할 필요가 있습니다.

관련 문제