Рефакторинг класса дизайн для передачи замысла дизайна


У меня есть следующий дизайн класса. Полный код доступен в разделе " Как достичь этой функциональности с помощью дженериков? ". Код работает нормально и решает проблему приведения, упомянутую в "рефакторинг кода, чтобы избежать приведения типа "

В классе RetailInvestmentReturnCalculator Метод GetInvestmentProfit() использует метод CalculateBaseProfit(), присутствующий в абстрактном базовом классе InvestmentReturnCalculator. Этот факт не очевиден из дизайна класса.

Вопрос

  1. Как отрефакторить этот класс замысел передать вышеупомянутый факт?
  2. Что такое руководство по проектированию, которое предотвратит такого рода ошибки проектирования?

Примечание: Мартин Фаулер: Дизайн Мертв? говорит

Что мы подразумеваем под архитектурой программного обеспечения? Для меня термин архитектура передает понятие основных элементов системы, частей, которые трудно изменить. Фундамент, на котором должно быть построено все остальное

Класс Диаграмма

Введите описание изображения здесь

Аннотация

public abstract class InvestmentReturnCalculator
{
    #region Public

    public double ProfitElement { get; set; }
    public abstract double GetInvestmentProfit();

    #endregion

    #region Protected

    protected  double CalculateBaseProfit()
    {
        double profit = 0;
        if (ProfitElement < 5)
        {
            profit = ProfitElement * 5 / 100;
        }
        else
        {
            profit = ProfitElement * 10 / 100;
        }
        return profit;
    }

    #endregion
}

public abstract class InvestmentReturnCalculator<T> : InvestmentReturnCalculator where T : IBusiness
{
    public T BusinessType { get; set; }
}

Бетон

public class RetailInvestmentReturnCalculator : InvestmentReturnCalculator<IRetailBusiness>
{
    public RetailInvestmentReturnCalculator(IRetailBusiness retail)
    {
        BusinessType = retail;
        //Business = new BookShop(100);
    }

    public override double GetInvestmentProfit()
    {
        ProfitElement = BusinessType.GrossRevenue;
        return CalculateBaseProfit();
    }
}
1 2

1 ответ:

Поле ProfitElement довольно уродливо. Я бы сделал его абстрактным свойством на InvestmentReturnCalculator и реализовал его в базовых классах (вместо установки значения) - это называется шаблонный метод pattern . Тогда вам не нужен метод GetInvestmentProfit().

public abstract class InvestmentReturnCalculator
{
    #region Public

    public abstract double ProfitElement { get; }

    #endregion

    #region Protected

    public double GetInvestmentProfit()
    {
        double profit = 0;
        if (ProfitElement < 5)
        {
            profit = ProfitElement * 5 / 100;
        }
        else
        {
            profit = ProfitElement * 10 / 100;
        }
        return profit;
    }

    #endregion
}

public abstract class InvestmentReturnCalculator<T> : InvestmentReturnCalculator where T : IBusiness
{
    public T BusinessType { get; set; }
}

public class RetailInvestmentReturnCalculator : InvestmentReturnCalculator<IRetailBusiness>
{
    public RetailInvestmentReturnCalculator(IRetailBusiness retail)
    {
        BusinessType = retail;
        //Business = new BookShop(100);
    }

    public override double ProfitElement {get { return BusinessType.GrossRevenue;}}

}