C# 需要关于接口的建议吗

C# 需要关于接口的建议吗,c#,interface,design-patterns,C#,Interface,Design Patterns,我只是需要一些关于我试图解决的问题的反馈 以下是问题的说明: 我公司出售一些产品,顾客可以在一定时期内付款。客户分为现有客户和新客户。为了让客户购买产品,我们会检查其信用状况,有时会要求客户存入保证金,保证金是可以退还的。一些客户与我们有良好的付款历史,因此我们不需要向他们收取保证金。为了实施评估,我设计了如下解决方案: public interface ICreditAssessor { CreditAssessment Process(); Decimal Calculate

我只是需要一些关于我试图解决的问题的反馈

以下是问题的说明:

我公司出售一些产品,顾客可以在一定时期内付款。客户分为现有客户和新客户。为了让客户购买产品,我们会检查其信用状况,有时会要求客户存入保证金,保证金是可以退还的。一些客户与我们有良好的付款历史,因此我们不需要向他们收取保证金。为了实施评估,我设计了如下解决方案:

public interface ICreditAssessor
{
    CreditAssessment Process();
    Decimal CalculateBond(BondCalculator bc);
}
public class BondCalculator
{
    List<IRiskEvaluator> riskEvaluators;

    public BondCalculator()
    {
        riskEvaluators = new List<IRiskEvaluator>();
    }

    public Decimal GetSuggestedBond()
    {
        Decimal riskAmount = 0;
        foreach (IRiskEvaluator ire in riskEvaluators)
        {
            Decimal tempRisk = ire.EvaluateRisk();

            if (tempRisk > riskAmount)
            {
                riskAmount = tempRisk;
            }
        }

        return riskAmount;
    }

    public void SetRiskEvaluator(IRiskEvaluator re)
    {
        this.riskEvaluators.Add(re);
    }
}
public interface IRiskEvaluator
{
    Decimal EvaluateRisk();
}
public class FinancialRiskEvaluator : IRiskEvaluator
{
    Decimal IRiskEvaluator.EvaluateRisk()
    {
        ... calculate risk amount
    }
}
定义了两个实现此接口的类

public class GoodClientProcessor : ICreditAssessor{
    ..... methods
}

public class OtherClientProcessor : ICreditAssessor{
    ..... methods
}
有一个类返回相应的处理器,这取决于客户是否与我们有良好的支付历史记录

此外,我还实现了一个
BondCalculator
,如下所示:

public interface ICreditAssessor
{
    CreditAssessment Process();
    Decimal CalculateBond(BondCalculator bc);
}
public class BondCalculator
{
    List<IRiskEvaluator> riskEvaluators;

    public BondCalculator()
    {
        riskEvaluators = new List<IRiskEvaluator>();
    }

    public Decimal GetSuggestedBond()
    {
        Decimal riskAmount = 0;
        foreach (IRiskEvaluator ire in riskEvaluators)
        {
            Decimal tempRisk = ire.EvaluateRisk();

            if (tempRisk > riskAmount)
            {
                riskAmount = tempRisk;
            }
        }

        return riskAmount;
    }

    public void SetRiskEvaluator(IRiskEvaluator re)
    {
        this.riskEvaluators.Add(re);
    }
}
public interface IRiskEvaluator
{
    Decimal EvaluateRisk();
}
public class FinancialRiskEvaluator : IRiskEvaluator
{
    Decimal IRiskEvaluator.EvaluateRisk()
    {
        ... calculate risk amount
    }
}
实现此接口的两个类如下所示:

public interface ICreditAssessor
{
    CreditAssessment Process();
    Decimal CalculateBond(BondCalculator bc);
}
public class BondCalculator
{
    List<IRiskEvaluator> riskEvaluators;

    public BondCalculator()
    {
        riskEvaluators = new List<IRiskEvaluator>();
    }

    public Decimal GetSuggestedBond()
    {
        Decimal riskAmount = 0;
        foreach (IRiskEvaluator ire in riskEvaluators)
        {
            Decimal tempRisk = ire.EvaluateRisk();

            if (tempRisk > riskAmount)
            {
                riskAmount = tempRisk;
            }
        }

        return riskAmount;
    }

    public void SetRiskEvaluator(IRiskEvaluator re)
    {
        this.riskEvaluators.Add(re);
    }
}
public interface IRiskEvaluator
{
    Decimal EvaluateRisk();
}
public class FinancialRiskEvaluator : IRiskEvaluator
{
    Decimal IRiskEvaluator.EvaluateRisk()
    {
        ... calculate risk amount
    }
}

现在调用所有这些都是通过一个方法完成的。相关代码如下:

ICreditAssessor creditAssessor = CreditAssessorFactory.GetAssessor(somecriteria);
CreditAssessment assessment = creditAssessor.Process();
.
.
.
BondCalculator bc = new BondCalculator();
bc.SetRiskEvaluator(new FinancialRiskEvaluator(xmlResults));
bc.SetRiskEvaluator(new ProductRiskEvaluator(productCost));
creditCheckProcessor.CalculateBond(bc);

这个设计可以吗?或者可以进一步改进吗?我看到的一个问题是,由于具有良好支付历史的客户不需要保证金,因此我仍然需要调用方法
CalculateBond
,并返回
0
,以获取保证金价值。这似乎有点不对劲。这一点可以改进吗?欢迎任何评论/建议。

您可以添加boolean BondRequired属性以明确意图,而不是依赖于人们来推断“零的键没有多大意义;开发人员一定希望该结果不代表任何键。”


然而,我同意Magnum的观点,即这已经比看起来需要的复杂,因此在类型中添加更多成员可能不是最好的选择。

这种设计可以,但绝对复杂;在我看来,对于两种不同类型的客户来说,这似乎有点过度设计了。似乎ICreditAssessor接口已经定义了CalculateBond,并在GoodCustomer和其他Customer类中实现了它。返回风险的函数是一个简单的大于比较的函数,因此我不明白为什么不能在这个函数中执行此操作,而不是向它发送一系列的BondCalculator。我想重申,这个设计非常好,只要不是第一年维护它,它就可以工作。italic不明白为什么不能在这个函数中完成这项工作,而不是向它发送一个完整的BondCalculator列表。italic我的理由是,如果需要任何其他类型的风险评估器,那么添加一个风险评估器比修改现有代码更容易。我喜欢你设计的设计,我喜欢phoog关于“BondRequired”属性的建议。如果没有更多地了解系统或更好地理解问题领域,我认为现在说您的设计“太复杂”还为时过早。特别是因为当你发布这样的问题时,要计算出要包含多少代码是很棘手的。对于一些开发人员来说,一堆过程代码比一个面向对象的设计“简单”,而其他开发人员则相反。我喜欢你设计的设计,我喜欢phoog关于“BondRequired”属性的建议。如果我将此属性添加到ICreditAssessor,这会使代码更容易理解吗:If(creditAssessor.isBondRequired()){//calculate bond BondCalculator bc=new BondCalculator();bc.SetRiskEvaluator(new Financial RiskEvaluator(xmlResults));bc.SetRiskEvaluator(new ProductRiskEvaluator(productCost));creditCheckProcessor.CalculateBond(bc);}在没有接口的情况下,我曾经有一个更简单的解决方案。如果添加接口使它看起来很复杂,那么在什么情况下我会使用它们?这种复杂性可能是合理的。我说这似乎比必要的更复杂,但评估是基于对问题的肤浅理解。