重构类设计以传达设计意图

时间:2014-02-05 13:59:55

标签: c# design-patterns class-design ooad template-method-pattern

我有以下课程设计。完整代码可在“How to achieve this functionality using Generics?”中找到。代码工作正常并解决了“Refactoring Code to avoid Type Casting

中提到的强制转换问题

RetailInvestmentReturnCalculator类中,GetInvestmentProfit()方法使用CalculateBaseProfit()抽象基类中的InvestmentReturnCalculator方法。这一事实在课堂设计中并不明显。

问题

  1. 如何重构此类设计以传达上述事实?
  2. 什么是防止此类设计错误的设计指南?
  3. 注意:Martin Fowler: Is Design Dead?

      

    软件架构是什么意思?对我而言,建筑这个术语传达了系统核心要素的概念,即难以改变的部分。必须建立其余部分的基础

    类图

    enter image description here

    抽象

    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 个答案:

答案 0 :(得分:2)

ProfitElement字段相当难看。我会在InvestmentReturnCalculator上将它作为一个抽象属性,并在基类中实现它(而不是设置值) - 这称为template method 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;}}

}