2017-09-14 7 views
0

を作成するためのベスト・プラクティス:継承 - の私は、これらのクラスを持っているとしましょう派生クラス

class Employee 
{} 

class SalaryManager 
{ 
    public void PaySalary(Employee e) 
    { 
     var bankService = GetBankService(); 
     bankService.Pay(e); 
    } 
} 

今、従業員が新しいプロパティPaymentMethodを持っており、給与が支払われている方法は、この列挙に依存します。

ifまたはswitchを使用すると、これを反映するように支払い給与を簡単に変更することができます。

class Employee 
{ 
    public enum PaymentMethod { get; set; } 
} 

class SalaryManager 
{ 
    public void PaySalary(Employee e) 
    { 
     if (e.PaymentMethod == Cash) 
     { 
      var bankService = GetBankService(); 
      bankService.Pay(e); 
     } 
     else if (e.PaymentMethod == Online) 
     { 
      // Different implementation 
     } 
    } 
} 

もちろん、私は、新しいPaymentMethodsが来る場合には、より簡単なアプリケーションを用意したいと思います。

したがって、私はSalaryManagerを基本クラス(またはインターフェイス)として持つことができ、2つの異なる特殊化を持つことができます。

class SalaryManager 
{ 
    public abstract void PaySalary(Employee e); 
} 

class CashSalaryManager : SalaryManager 
{ 
    public override void PaySalary(Employee e) 
    { 
     var bankService = GetBankService(); 
     bankService.Pay(e); 
    } 
} 

class OnlineSalaryManager : SalaryManager 
{ 
    public override void PaySalary(Employee e) 
    { 
     // Different implementation 
    } 
} 

私の懸念は、このSalaryManagerクラスのインスタンスを作成することです。誰がこれに責任を負うべきですか?

従業員にこれについて知ってもらうオプションが1つあります。言い換えれば、従業員は給与の支払方法を知っているマネージャークラスを知ってもらう必要があります。

この場合、Employeeにも2つの異なる派生クラスを用意する必要がありますか?

また、このマネージャクラスの作成または作成に関連するFactoryクラスを用意する必要がありますか?

static class SalaryFactory 
{ 
    public static SalaryManager CreateSalaryManager(Employee e) 
    { 
     SalaryManager manager = null; 
     if (e.PaymentMethod == Cash) 
     { 
      manager = new CashSalaryManager(); 
     } 
     else if (e.PaymentMethod == Online) 
     { 
      manager = new OnlineSalaryManager(); 
     } 
     else 
     { 
      thrown new Exception ("No Manager class found for the payment type"); 
     } 
    } 
} 

これは、異なるManagerクラスで発生した場合はどうなりますか?言い換えれば、Employeeタイプに応じて動作が異なる3つの異なるManagerクラス(それぞれTaxCalculationManager)があります。これで上記の解決策が変わるでしょうか?

+0

この質問はあまりにも幅広く聞こえており、あなたは既に回答(インターフェイス)を知っているように聞こえます。 – buffjape

+0

戦略パターン。 –

答えて

0

コントロールコンテナのこの反転とユーザー反転の行に沿って、私はすべてのISalaryManagerの実装をSalaryPaymentManagerに挿入します。次に、お支払い方法ごとにISalaryManagerを新たに実装することです。

public class Employee 
{ 

} 

public interface ISalaryManager 
{ 
    void PaySalary(Employee e); 
    bool HandlesPaymentType(string paymentType); 
} 

public class CashSalaryManager : ISalaryManager 
{ 
    public void PaySalary(Employee e) 
    { 
     var bankService = GetBankService(); 
     bankService.Pay(e); 
    } 

    public bool HandlesPaymentType(string paymentType) 
    { 
     return paymentType == "Cash"; 
    } 
} 

public class OnlineSalaryManager : ISalaryManager 
{ 
    public void PaySalary(Employee e) 
    { 
     // Different implementation 
    } 

    public bool HandlesPaymentType(string paymentType) 
    { 
     return paymentType == "Online"; 
    } 
} 

public class SalaryPaymentManager 
{ 
    private readonly IEnumerable<ISalaryManager> _salaryManagers; 

    public SalaryPaymentManager(IEnumerable<ISalaryManager> salaryManagers) 
    { 
     _salaryManagers = salaryManagers; 
    } 

    public void PaySalary(string paymentType, Employee employee) 
    { 
     var salaryManager = _salaryManagers.FirstOrDefault(x => x.HandlesPaymentType(paymentType)); 

     if (salaryManager == null) 
      throw new NotImplementedException(); 

     salaryManager.PaySalary(employee); 
    } 
} 
関連する問題