2012-06-27 2 views
2

계층 적 방법으로 구성된 클래스 묶음으로 제 3 자 어셈블리를 사용하고 있습니다. 이것들은 private 생성자를 가지며, 한 레벨 상위의 다른 클래스의 인스턴스에서 CreateXxx() 메소드를 호출하여 인스턴스화됩니다. 계층 구조의 맨 위에는 싱글 톤 (singleton) 클래스가 사용됩니다.개체의 생성과 마무리를 캡슐화하는 좋은 방법은 무엇입니까?

TopClass top = TopClass.GetInstance(); 
SecondLevelClass secondLevel = top.CreateSecondLevelElement(); 
ThirdLevelClass thirdLevel = secondLevel.CreateThirdLevelElement(); 

마찬가지로, 마무리가 CreateXxx()에 사용 된 것과 같은 객체에 일이있는 DeleteXxx() 방법을 사용하여 수행됩니다 : 예를 들어, 응용 프로그램 코드는 다음과 같이 보인다.

나는이 특별한 접근법이 취해진 이유에 대해 언급하지 않을 것입니다. 그러나, 나는 public 생성자가 있습니까 클래스 내 자신의 세트와 함께 이러한 클래스의 생성을 캡슐화하고 싶은 그러한 코드는 다음과 같이, 더 잘 볼 것입니다 :

// No TopClass anymore, see explanation below 
MySecondLevelClass secondLevel = new MySecondLevelClass(); 
MyThirdLevelClass thirdLevel = new MyThirdLevelClass(secondLevel); 

내 초기 접근 방식은 MyXxx 클래스했다 해당 생성자에서 해당 CreateXxx() 메서드를 호출하고 결과에 대한 참조를 유지 관리합니다. 또한 완료시에 DeleteXxx() 메소드를 호출하려면 생성자 매개 변수에 대한 참조가 필요합니다. 이를 위해 IDisposable을 구현하고 안에 DeleteXxx()을 호출하려고합니다.

TopClass은 응용 프로그램 개발자가 SecondLevelClass 인스턴스를 만들고 파괴하기위한 용도로 사용되기 때문에 불필요 해졌습니다. 이것은 이제 MySecondLevelClass 생성자 내부의 내부에서 발생합니다.

나는 이것이 기술적으로 소리 같다고 생각합니다. 내가 만나는 유일한 문제는 원래 클래스가 많은클래스를 통해 노출되기를 원하는 많은 메소드를 가진 인터페이스를 구현한다는 사실입니다. 내 자신의 클래스에서 모든 메서드를 재정의하는 것을 기대하지 않고 모든 호출을 "원본"클래스의 인스턴스에 대한 캡슐화 된 참조로 전달하기 만합니다. 도트 연산자에 과부하 같은 것을 할 수 있다면 좋을 것입니다. 또는 원래 클래스의 인스턴스에 대한 캡슐화 된 참조가 실제로 인터페이스를 구현한다는 것을 컴파일러에 알리는 것이 좋습니다. 즉 VMT에 여분의 간접 참조를 추가하는 것입니다.

이러한 옵션은 물론 지원되지 않으며 모든 복제 방법에 대한 방법을 찾지 못했습니다. 아무도 똑똑한 방법으로 이것을하는 방법에 대한 아이디어가 있습니까? 모든 의견은 감사드립니다. 미리 감사드립니다. 난 당신처럼 그것이 가장 좋은 방법 아니라는 것을 알고


public class Concrete : SomeInterface 
{ 
    private Concrete() 
    { 
     //instantiate other classes here 
    } 
    public string GetAString() 
    { 
     return string.Empty; 
    } 

    public static Concrete GetInstance() 
    { 
     return new Concrete(); 
    } 

} 

public class Wrapper : SomeInterface 
{ 
    public Wrapper() 
    { 
     this.concrete = Concrete.GetInstance(); 
    } 
    Concrete concrete { get; set; } 
    public string GetAString() 
    { 
     this.concrete.GetAString(); 
    } 
} 

public interface SomeInterface 
{ 
    string GetAString(); 
} 

-

+3

* * "마찬가지로, 파괴는 DeleteXxx() 메소드를 사용하여 수행됩니다"- 즉, –

+0

원래 클래스에서 상속 그냥 필요한 추가에서 당신을 중지 무엇 ... C#으로 볼 수 ... 홀수를 연관? –

+0

@EugenRieck 개인 생성자가있는 클래스에서 상속받는 경우 공용 생성자를 사용할 수 없습니다. 그것은 – theMothaShip

답변

0

당신이 (내가 아는 한)이 작업을 수행 할 수있는 유일한 방법은 다음과 같은 일을하는 것입니다 래핑하는 클래스의 각 인터페이스 멤버에게 수동으로 호출해야하지만 목표를 달성 할 수 있습니다.

T4 코드 템플릿을 사용해 보시겠습니까? 이 상황을 자주 접한다면 (그리고 인터페이스가 바뀌면) 앞으로의 시간을 절약 할 수있을 것입니다.

+0

사실 이것은 설명하려고했던 초기 접근법입니다. 그것은 작동하지만, 제 경우에는'SomeInterface'는 수동으로 호출해야하는 약 30 개의 메소드를 가지고 있습니다. 랩핑해야하는 다른 10 개의 클래스에도 동일하게 적용됩니다. 나는이 수작업을 필요로하지 않는 솔루션을 기대하고있었습니다. –

+0

@Reinier T4 코드 템플릿은 지루한 코드를 생성하는 데는 효과적 일 수도 있지만 궁극적으로 상황을 받아들이는 것 이상의 작업 일 수도 있습니다 ... – theMothaShip

+0

전에 T4로는 아무 것도하지 않았습니다. 감사합니다. –

1

기존 클래스를 래핑하는 대신 아마도 구조 인을 빌더 패턴과 같은 것을 사용하여 래핑 할 수 있습니다. 'TopClass o = new TopClass()'구문을 얻지는 못하지만 이와 같은 구조 패턴은 잘 이해되어 코드 이해를 향상시켜야합니다.

빌더는 다음과 같을 수 있습니다.

public class OtherAssemblyBuilder 
{ 
    public TopClass Build() 
    { 
     return TopClass.GetInstance(); 
    } 

    public SecondLevelClass Build() 
    { 
     TopClass top = TopClass.GetInstance(); 
     return top.CreateSecondLevelElement(); 
    } 

    public ThirdLevelClass Build() 
    { 
     TopClass top = TopClass.GetInstance(); 
     SecondLevelClass secondLevel = top.CreateSecondLevelElement(); 
     return secondLevel.CreateThirdLevelElement(); 
    } 
} 
+0

그건 다른 트위스트 ... 감사합니다. 이 접근 방식의 문제점은 객체를 완성한 것과 같은 객체에서'DeleteXxx()'메소드를 사용하여 완료해야하는 객체의 마무리입니다. 나는 그것을 반영하기 위해 질문에 문장을 추가했다. 이를 달성하기 위해서는 원래 클래스 자체에서 이미 수행 된 기능의 복제이며 상당히 복잡 할 수있는 OtherAssemblyBuilder 클래스의 전체 생성 계층 구조를 유지해야합니다. 나는 그것을 더 생각할 것이다. –

관련 문제