2013-06-24 3 views
1

그래서 개체가 특정 생성자를 사용하여 인스턴스화되었는지 확인하는 것에 대한 질문이 있습니다. 검색 엔진의 일부인 SearchWithTwoLevelCore라는 클래스가 있습니다. 그것은이 같은 생성자가 : S, lvl1 및 lvl2 모든 민간 분야가 공공 클래스의 객체를 보유하고있는 클래스에 선언되어있다인스턴스가 제대로 인스턴스화되었는지 확인하는 가장 좋은 방법

public SearchWithTwoLevelCache(ISearchCore s, ICurrentTimeProvider tp) 
    { 
     //Initialize the two levels. 
     S=s; 
     lvl2 = TimeBoundedQueryCache(s.AsQueryDataSource, tp, TimeSpan(24,0,0)); 
     lvl1 = SizeBoundedQueryCache(lvl2, 10); 


    } 

. 그럼 내가 SearchWithTwoLevelClass 안에 상주하고 싶은 퍼블릭 메소드를 가지고 있지만 먼저 SearchWithTwoLevelCache를 만드는데 사용 된 생성자가 위의 메소드인지 확인하기를 원한다. 그렇지 않으면 메소드가 제대로 실행되지 않고 예외가 발생한다. 티. 이 작업을 수행하는 가장 좋은 방법은 무엇입니까? 미리 감사드립니다.

+1

여러 생성자가 있고 해당 메서드가 호출 된 생성자를 기반으로하는 개체의 상태에 의존하는 경우 이러한 인수를 함수 호출 자체로 이동하는 것이 좋습니다. 그렇게하면 시퀀스 종속성이 없으며 메서드를 호출 할 수있는 유일한 방법은 성공하는 데 필요한 데이터를 사용하는 것입니다. – dash

+0

"인스턴스가 올바르게 인스턴스화되었는지 확인하는 가장 좋은 방법은 아마도"* SearchWithTwoLevelCache를 만드는 데 사용 된 생성자가 위의 것이 었는지 확인하지 않을 것입니다. " – haim770

답변

4

이것은 Liskov Substitution Principle의 중요성을 보여주는 좋은 예입니다. 나는 this answer에서 사용 된 이미지를 아주 좋아합니다.

클래스에 여러 생성자가 있고 메소드의 성공 여부가 호출 된 생성자에 따라 다르면 몇 가지 선택 사항이 있습니다.

여기서 중요한 문제는 개체 상태가 호출되는 생성자에 따라 달라지는 것입니다. 이는 구현을 어떻게 표현하는지에 관계없이 수업 전반에 걸친 상태 점검의 확산으로 이어지는 최고의 설계 기법은 아닙니다.

1) 작은 물체

여기 아이디어는 생성자 만 클래스를 실행하는 데 필요한 데이터를 요구해야한다는 것입니다으로 객체를 리팩토링. 서로 다른 양의 인수와 데이터를 요구하는 생성자가 여러 개있는 경우이 클래스는 실제로 여러 개의 다른 객체를 나타냅니다.

2) 메소드에 대한 데이터 요구 사항을 시행하십시오.

public SearchWithTwoLevelCache(ISearchCore s, ICurrentTimeProvider tp) 
{ 
    //Initialize the two levels. 
    S=s; 
    lvl2 = TimeBoundedQueryCache(s.AsQueryDataSource, tp, TimeSpan(24,0,0)); 
    lvl1 = SizeBoundedQueryCache(lvl2, 10); 
} 

그것은 실제로 함수에 대한 전제 조건 인 경우이 상태가 사실로, 클래스 자체가 필요하지 않다는 주장 할 수있다, 다음 함수 자체의 요구 사항을 확인하십시오. 이것은 모호성을 제거합니다.

클래스 그러므로 될 수 있습니다 : 예를 들어

public SearchWithTwoLevelCache(ISearchCore s) 
{ 
    S = s; 
} 

public Whatever PerformTwoLevelSearch(ICurrentTimeProvider tp) { } 

.

여기의 아이디어는 클래스의 상태에 절대적으로 필요한 데이터만을 생성자에서 제공하는 것입니다.

물론 메서드 수준에서 검사를 구현하고 예외를 throw 할 수 있지만 클래스를 사용하는 사람들에게는 매우 실망 스러울 수 있습니다.함수 1을 호출하려면 생성자 2를 호출하고 다른 변수를 설정해야한다는 것을 어떻게 알았습니까? 그들은 사용할 인터페이스를 어떻게 알 수 있습니까? 그렇기 때문에 기능의 조건을 사용하고 유지하는 것이 훨씬 간단합니다.

앞으로이 클래스를 확장하는 것도 어려울 것입니다. 메소드의 성공이 다른 여러 메소드 나 생성자를 먼저 호출하는 경우, 리팩토링과 로직 변경으로 인해 모든 클라이언트가 변경됩니다.

+0

위대한 답변, 감사합니다! –

1

publicboolean property을 클래스 내에 넣을 수 있으며 constructor의 경우 true으로 설정할 수 있습니다. 이 속성의 기본값은 false 일 수 있습니다.

개체가 obj1 인 경우 함수를 호출하기 전에이 부울을 확인할 수 있습니다.

if(obj1.public_property) 
    // do function call 

이것은 단지 해결책 일뿐입니다. 이것보다 나은 해결책이있을 수 있습니다.

0

빠른 해결책 (좋지 않음)은 나중에 코드에서 모든 부분을 확인하여 플래그가 지정된 구성자를 나타냅니다.

F #에서 실제로 필요한 것은 Discriminated Unions입니다. 그러나 우리는 C#을 사용하지 않기 때문에 클래스를 interface으로 추상화 한 다음 해당 인터페이스에 대해 서로 다른 구현을 제공해야합니다.

이제 각 구체적인 구현에 대해 메소드 오버로드를 사용하여 어떤 구체적인 구현을 사용할 것인지 결정할 수 있습니다.

관련 문제