2008-09-16 15 views
1

これらの2つのクラスをどのようにリファクタリングして類似性を抽象化しますか?抽象クラスですか?単純な継承?リファクタリングされたクラスはどのように見えますか?この場合には、私見より複雑であると思われるものを因数分解 - 彼らがあるとして、私はおそらくそれらを残して、より多くのをどうするつもりされていない場合2つの基本クラスをリファクタリングする

public class LanguageCode 
{ 
    /// <summary> 
    /// Get the lowercase two-character ISO 639-1 language code. 
    /// </summary> 
    public readonly string Value; 

    public LanguageCode(string language) 
    { 
     this.Value = new CultureInfo(language).TwoLetterISOLanguageName; 
    } 

    public static LanguageCode TryParse(string language) 
    { 
     if (language == null) 
     { 
      return null; 
     } 

     if (language.Length > 2) 
     { 
      language = language.Substring(0, 2); 
     } 

     try 
     { 
      return new LanguageCode(language); 
     } 
     catch (ArgumentException) 
     { 
      return null; 
     } 
    } 
} 

public class RegionCode 
{ 
    /// <summary> 
    /// Get the uppercase two-character ISO 3166 region/country code. 
    /// </summary> 
    public readonly string Value; 

    public RegionCode(string region) 
    { 
     this.Value = new RegionInfo(region).TwoLetterISORegionName; 
    } 

    public static RegionCode TryParse(string region) 
    { 
     if (region == null) 
     { 
      return null; 
     } 

     if (region.Length > 2) 
     { 
      region = region.Substring(0, 2); 
     } 

     try 
     { 
      return new RegionCode(region); 
     } 
     catch (ArgumentException) 
     { 
      return null; 
     } 
    } 
} 

答えて

0

リファクタリングが必要な理由がない限り(近い将来のようなクラスを追加する予定であるため)、このような小さく複雑な例のデザインを変更すると、メンテナンスやオーバーヘッドの増加を克服できますシナリオ。とにかく、ここではジェネリックとラムダの式に基づいたデザインが可能です。

public class TwoLetterCode<T> 
{ 
    private readonly string value; 

    public TwoLetterCode(string value, Func<string, string> predicate) 
    { 
     this.value = predicate(value); 
    } 

    public static T TryParse(string value, Func<string, T> predicate) 
    { 
     if (value == null) 
     { 
      return default(T); 
     } 

     if (value.Length > 2) 
     { 
      value = value.Substring(0, 2); 
     } 

     try 
     { 
      return predicate(value); 
     } 
     catch (ArgumentException) 
     { 
      return default(T); 
     } 
    } 

    public string Value { get { return this.value; } } 
} 

public class LanguageCode : TwoLetterCode<LanguageCode> { 
    public LanguageCode(string language) 
     : base(language, v => new CultureInfo(v).TwoLetterISOLanguageName) 
    { 
    } 

    public static LanguageCode TryParse(string language) 
    { 
     return TwoLetterCode<LanguageCode>.TryParse(language, v => new LanguageCode(v)); 
    } 
} 

public class RegionCode : TwoLetterCode<RegionCode> 
{ 
    public RegionCode(string language) 
     : base(language, v => new CultureInfo(v).TwoLetterISORegionName) 
    { 
    } 

    public static RegionCode TryParse(string language) 
    { 
     return TwoLetterCode<RegionCode>.TryParse(language, v => new RegionCode(v)); 
    } 
} 
2

それは、依存しています。

0

これはやや単純な質問ですが、私にとっては宿題のようにうなずいています。

あなたは明らかにコードの共通のビットを見ることができ、私はあなたがそれをスーパークラスに入れることであなた自身で試みることができると確信しています。だ

0

あなたは多分、言語コードと地域コードの両方を格納し地域と言語のプラスも「表すen_GB」などの文字列を可能にするものでparse関数のためのアクセサを持ってLocaleクラスにそれらを組み合わせることができ...

ロケールをどのように見てきたかは、さまざまなフレームワークで処理されます。

0

静的メソッドのために、これらの2つは、そのままではリファクタリングを行いません。

基本クラスの型を返すベースクラス(いくつかの種類の追加のヘルパークラスが必要です)に、何らかのファクトリメソッドがあります。

余分なコードの量とその後の適切なタイプへのキャストを考えると、それは価値がありません。

0

より優れたジェネリックベースのソリューションがあると確信しています。しかし、まだそれを撃った。

EDIT:静的メソッドをオーバーライドすることはできません。したがって、保持してTwoLetterCodeオブジェクトを使用してキャストすることですが、他の人が既に指摘しているように、むしろ役に立たない。

これはいかがですか?

public class TwoLetterCode { 
    public readonly string Value; 
    public static TwoLetterCode TryParseSt(string tlc) { 
     if (tlc == null) 
     { 
      return null; 
     } 

     if (tlc.Length > 2) 
     { 
      tlc = tlc.Substring(0, 2); 
     } 

     try 
     { 
      return new TwoLetterCode(tlc); 
     } 
     catch (ArgumentException) 
     { 
      return null; 
     } 
    } 
} 
//Likewise for Region 
public class LanguageCode : TwoLetterCode { 
    public LanguageCode(string language) 
    { 
     this.Value = new CultureInfo(language).TwoLetterISOLanguageName; 
    } 
    public static LanguageCode TryParse(string language) { 
     return (LanguageCode)TwoLetterCode.TryParseSt(language); 
    } 
} 
+0

残念ながら、TryParseメソッドが静的でないため、残念ながらうまく機能しません。 TryParseは、新しいLanguageCodeまたはRegionCodeオブジェクトを返すファクトリメソッドには有効です。あなたの例では、最初にオブジェクトを作成する必要があります。 TryParseは静的であるため、ベースTryParseをオーバーライドすることはできません。 –

+0

残念ながら、TwoLetterCodeの新しいインスタンスは抽象的であるため作成できません(return new TwoLetterCode(tlc)を参照)。私はTwoLetterCodeのクラスのdelcarationから "抽象"を取り除くことができますが、保護されている型だけでTwoLetterCodeを作成できるようにする必要はありません。 – core

0
  1. (例えばAbstractCode<T>
  2. 最後に

    protected override RegionCode GetConstructor(string code) 
    { 
        return new RegionCode(code); 
    } 
    
  3. のように基底クラスに

    protected T GetConstructor(string code); 
    
  4. オーバーライドのような抽象メソッドを追加し、一般的な基本クラスを作成し、実行します0と同じ両方のリファクタリングます、例えば

    protected override GetIsoName(string code) 
    { 
        return new RegionCode(code).TowLetterISORegionName; 
    } 
    

。 Chris Kimptonは、その努力が価値あるものかどうかという重要な疑問を提起します。

関連する問題