2013-11-20 3 views
1

나는 커다란 수업을 가지고 있는데, 'Country'라고 부르 자. 목록 상태, 연령 등과 같은 모든 종류의 속성을 가지고 있습니다.이 디자인 패턴의 이름은 무엇입니까? (만약 그렇다면)

실생활에서 저는 사용자가 클라이언트가 제공하는 서비스에 대한 구독을 등록하는 ASP.NET 응용 프로그램을 작성하고 있습니다. 이 애플리케이션 양식에는 많은 속성이 필요하며 데이터 모델을 대표하는 주요 클래스 중 하나가 너무 부풀어 오르기 때문에 컴포지션을 통해 작은 클래스로 나누기를 원하지만 상위 클래스에 연결된 하위 클래스에는 여전히 속성이 있습니다. 수업.

이 예제에서는 일을 단순하게 유지하고 자동차 예제를 참조하십시오. 설정의 빠른 샘플을 만들어 지금

public static class WorldDatabase 
{ 
    public static List<Country> Countries {get;set;} 
} 

class Country 
{ 
    public int Age {get;set;} 
    public string Name{get;set;} 
    public List<State> States{get;set;} 
} 

class State 
{ 
    public string CountryName{get;set;} 
    public string Capitol{get;set;} 
    public List<string> Cities{get;set;} 
} 

: : 그래서 우리는 다음과 같습니다 클래스라는 나라가

var states = new List<States>(); 
states.Add(new State(){CountryName="United States", 
         StateName="NJ", 
         Capitol="Trenton"}); 

WorldDatabase.Countries.Add(new Country{Age=237, 
           Name="United States", 
           States=states}); 

WorldDatabase.Countries[0].Name="US"; 

//assert obviously fails because the names are not linked 
Assert.IsEqual(WorldDatabase.Countries[0].Name == states[0].CountryName); 

그래서 내가 해결하기 위해 노력하고있어 문제 : 무엇이 가장 좋은 방법 두 속성을 연결 하시겠습니까? 내가 생각해 낸 방법은 부모 (국가)의 인스턴스를 State 클래스에 주입하는 것이다. 그러나 나는 부모가 부모가되어서는 안될 때 부모가 변화를 겪는 것에 대해 우려하고 있습니다. 또한 내가 알지 못하는 코드를 적게 사용하는 방법이있는 것처럼 보입니다. 다음은 내가 생각해 낸 두 가지 방법입니다.

//does a one-time 'binding' 
class State 
{ 
    public void BindFrom(Country country) 
    { 
     CountryName=country.Name; 
    } 
    public string CountryName{get;set;} 
    public string Capitol{get;set;} 
    public List<string> Cities{get;set;} 
} 

//tracks the parent forever 
class State 
{ 
    private readonly Country _parent; 
    public State(Country parent) 
    { 
     _parent = parent; 
    } 

    public string CountryName 
    { 
    get 
     { 
     return _parent.Name; 
     } 
    } 
    public string Capitol{get;set;} 
    public List<string> Cities{get;set;} 
} 

이 패턴의 이름은 무엇입니까 (있는 경우)? 나는 그것에 대해 더 많이 읽고 싶다 .. 그리고 대안이 있는가?

+2

capitAl, 국회 의사당은 건물입니다 –

+0

국가를 편집 할 수 없도록 국가를 제한하려면 2 번째 옵션을 유지하고 필요한 게터 만 제공하는 인터페이스를 추가하십시오 –

답변

1

귀하의 probelem는 부모 클래스에 의해 상속 구현 된 인터페이스 또는 기본 클래스을 /를 사용하여 해결할 수 있습니다.

인터페이스/기본 클래스는 자식이 보거나 수정할 수 있도록하려는 매개 변수 만 노출해야합니다. 전체 구현 만이 서면을 허용해야합니다.

class CountryBase 
{ 
    public string Name { get; protected set; } 
} 

class Country: CountryBase 
{ 
    public string Name { get { return base.Name;} set { base.Name = value;} 
} 

Country 지금 CountryBase.Name에 대한 세터의 모든 권한을가집니다. State 인스턴스에 CountryBase 만 전달하십시오.

또는 인터페이스 (권장 사항)로;

class ICountry 
{ 
    string Name { get;} 
} 

class Country: ICountry 
{ 
    public string Name { get; set; } 
} 
+0

디커플링에 대해서는 CountryBase 대신 Nameable을 사용하는 것이 좋습니다. –

+0

@ArlaudAgbePierre 간단히하기 위해'Name' 속성 만 사용했습니다. 'State'가 형제의 가시성을 필요로하는 경우 유사한 'States' 속성이있을 수 있습니다. 낮은 결합력 (디커플링 - 나는 그것을 위해 다양한 인터페이스를 완벽하게 추천합니다!)이 목표가 아닙니다. 이 문제는 캡슐화 중 하나입니다. – Gusdor

+0

그래도 Base는 가장 적합하지 않은 접미사 중 하나입니다. 게다가 추상 클래스에 자주 사용됩니다 (Microsoft에서 명시 적으로 권장하지는 않지만). C# 인터페이스라면 ICountry라고해야합니다. 또한,이 질문에는 실제로 대답하지 않습니다.이 질문은 "인터페이스에 이름을 국가 인스턴스에 전달하는 가장 좋은 방법은 무엇입니까"라고 요약 할 수 있습니다. 제공되는 솔루션은 모두 가능한 답변입니다. –

1

내가 그 당신의 예를 가까이 볼 수있는 유일한 패턴은 위임 패턴 (이름의 도서관을 찾는 중 상태의 부모에 위임)입니다.

귀하의 사례는 농축과 구성의 차이점을 상기시켜줍니다. 국가는 여러 주를 보유하고 있으며 국가에 속하지 않은 주를 가질 의미가 없습니다.

두 솔루션 모두 장단점이 있다고 생각합니다. 그러나 나는 생성자에서 국가를 전달하는 대신 CountryName 만 알 수 있도록 첫 번째 인스턴스를 변경했습니다. 국가 이름이 생성자에서 변경된 경우 CountryName에 대한 공용 설정자를 사용하여 데이터 캡슐화를 중단하는 것은 무엇입니까?

+0

조언을 주셔서 감사합니다 .. 실제 생활에서, 나는 그 생성자에서 일어나는 linq 쿼리 및 다른 여러 속성을 가지고 .. 왜 내가 전체 클래스에서 패스가 – dferraro

+0

진짜 질문은 : 비동기 적으로 변경하지 않고 국가는이 변화를 알고 있습니까? 그렇지 않다면 첫 번째 해결 방법이 적절하다고 판단됩니다. 그렇지 않으면 부모를 영원히 지켜야합니다. –

0

국가에 속한 국가에 대한 참조가 있어야합니다. 이런 종류의 패턴을 Object composition이라고합니다.

+0

이전에 저의 대답에서 언급 한 것과 같이 조롱입니다. –

+0

그렇습니다. 집계 일 수도 있지만 구현 클래스는 동일하게 유지되어야합니다. 국가는 국가에 대한 참조가 있어야합니다. 국가 이름을 알고 자하는 클라이언트는 state.Country.Name을 호출 할 수 있지만 state.Country.States를 가진 모든 형제 상태를 찾을 수도 있습니다. 그것은 내 의견으로는 훨씬 더 견고한 해결책이다. – Dtex

0

나는 이것이 어떤 패턴인지 모르지만 예제를 보면 속성 내용이 변경되고 동일한 속성 내용을 공유해야하는 모든 다른 개체가 변경되지 않을 가능성이 있다고 생각합니다. 내가 잘못 알았을 때 나는 내 대답을 제거 할 것이다. 왜냐하면 다음은이 가정에 근거하기 때문이다.

기본 클래스 또는 인터페이스를 사용하여 문제를 해결하십시오. 둘 다 같은 이름을 가진 속성을 가지고 있는지 확인합니다. 가능하다면. 다른 패턴을 구현하려고합니다.

이 작업을 수행하는 한 가지 방법은 Country 개체와 State 개체 모두에서 참조가있는 개체를 만들 수 있다는 것입니다. 객체 호출을 생성하는 것보다 Name 객체의 내용을 제어하는 ​​객체는 Controller입니다. 이름을 변경해야한다면 컨트롤러가 호출되고 이에 따라 내용이 변경됩니다. Country 개체와 State 개체의 속성을 Readonly으로 설정했는지 확인하십시오.

더 간단하지만 효과적인 방법은 속성을 변경할 수있는 유일한 컨트롤러 인 '컨트롤러'를 만드는 것입니다. 두 속성 사이에 참조가 필요하지 않습니다. 컨트롤러가 속성을 변경할 수있는 유일한 개체 인 경우 컨트롤러에서 United States의 이름을 US으로 변경하는 메서드를 만듭니다. Contoller가 모든 국가 및 주 컬렉션에 대해 알고있는 경우 원래 컨텐트를 조회하여 새 컨텐트로 변경하여 속성을 변경할 수 있습니다. 국가에 대한 컨트롤러와 상태에 대한 컨트롤러가 각각 두 개있는 경우 다른 컨트롤러에서 동일한 변경을 수행 할 수있는 메서드를 호출 할 수 있습니다. (변경 방법의 종류는 인터페이스 또는 기본 클래스로 강제 될 수 있습니다.)

이렇게 생각하십시오. 의자에는 다리 모음이 있지만 의자 자체는 이것을 모릅니다. 그것은 단지 의자입니다. 다리가 4 개인 사람의 소유자 또는 소유자입니다. 그것은 단지 3 개의 다리를 가질 수 있습니다. 다리가 부러지면 목수에게 의자 다리를 수리하라고 지시합니다. 3 개의 다리가 달린 의자에 여분의 다리를 추가하려면 의자가 아닌 목수에게 알려야합니다. 귀하의 경우 국가 이름이 변경되면 국가 담당자에게 알려주십시오. 그런 다음 국가 이름이 변경됩니다. 그 나라 자체에는 이름 만 있습니다.

이 솔루션의 문제점은 이미 큰 코드 기반이 있고 많은 사람들이이 작업을 수행 한 프로젝트에서 다른 작업 방법을 소개한다는 것입니다. 이전 코드는 새로운 코드 작성 방법을 따르지 않아 코드의 나머지 부분에 이상하게 보일 수 있습니다. 또한 전체 코드 기반을 리팩토링 할 때 대부분의 경우 실행 가능하거나 권장 할만한 것이 아닙니다. 물론이 새로운 방식을 천천히 도입하는 것이 선택 사항 일 수 있습니다.

관련 문제