【问题标题】:Want to avoid downcasting inside a Strategy passed to a Composite想要避免在传递给 Composite 的 Strategy 中向下转换
【发布时间】:2011-08-21 00:20:56
【问题描述】:

这是我在金融行业的问题领域:

资产 ========== 资产母公司 资产ID + compareTo(资产另一个资产) 投资组合:资产 ----------------- 姓名 风险限额 上市股票 + compareTo(资产另一个资产) + Composite.CompareTo(投资组合,CompareRules)。 股票:资产 -------- 市场 数量 公司 + compareTo(资产另一个资产) 另一种股票:股票 -------------------- 一些其他的财产 + compareTo(资产另一个资产)

我已将复合模式应用于 *Portfolio*s 中的 *Stock*s 结构。我想有一种干净的方式来自定义这个复合的 compareTo 方法。也就是说,AnotherStock 将始终与另一个 AnotherStock、Stocks 与 Stocks 进行比较。在我看来,这就像策略模式。

我想做如下的事情(伪代码)

差异=composite.CompareTo(anotherComposite,CompareRules)。 Composite.CompareTo 将类似于: 比较规则.比较(this.Stocks[currentAssetID],otherComposite[currentAssetID])

ComparisonRules.Compare(Asset a, Asset b) 会做一些丑陋的事情:

if(a is Stock and b is Stock) : 转换为股票并进行基于股票的比较 else if (a is AnotherStock and b is AnotherSTock): 转换为 AnotherStock

有没有一种方法可以编写ComparisonRules,这样我就不必向下转换但仍然提供自定义的ComparisonRules 对象?

【问题讨论】:

  • 您的问题并不完全清楚; composite.CompareTo 是什么?假设您在问题开始时提供了一个类图(排序),composite.CompareTo 的命名是无效的。同样“自定义此组合的compareTo 方法”也不完全清楚;您的意思是您希望能够提供一个规则列表,并且每个规则必须处理AnotherStockStock 等?
  • >您的意思是您希望能够提供规则列表,并且每个规则必须处理AnotherStock、Stock、:是的
  • 比较规则是否适用于两只股票(即比较一只股票与另一只股票)或两个股票列表(将一个列表与另一个比较)?

标签: c# oop design-patterns


【解决方案1】:

从规则的角度来看,听起来您需要的是泛型。如果你按照这些思路定义一些东西:

public class ComparisonRule<TStock> where TStock : Stock
{
    public int Compare(TStock lValue, TStock rValue)
    {
        ...
    }
}

这将保证只接受TStock 或以下的类型。例如,如果我有一个 ComparisonRule&lt;AnotherStock&gt;,则只能传入 AnotherStock 或以下的类型。但是,如果您希望能够定义一个可以比较 @987654325 的规则,则可能需要重新考虑您的类型层次结构@ 但不是AnotherStock。您应该考虑拥有一个共同的祖先,但具体的股票类型应该在不同的继承树中。

换句话说,你有这个:

              Stock
                |
    --------------------------
   |                          |
OneStock                AnotherStock 

这将允许您定义一个可以将任何StockComparisonRule&lt;Stock&gt; 进行比较的规则,或者一个只能将OneStockComparisonRule&lt;OneStock&gt; 进行比较的规则。

然而,这并不能帮助您理清如何知道哪些Stock 对象将传递给更高级别的哪些规则。为此,您需要能够定义一个不太具体的 ComparisonRule 版本,我们可以通过接口来做到这一点:

public interface IComparisonRule
{
    bool CanCompare(Stock lValue, Stock rValue);
    int Compare(Stock lValue, Stock rValue);
}

public abstract class ComparisonRule<TStock> : IComparisonRule where TStock : Stock
{
    bool IComparisonRule.CanCompare(Stock lValue, Stock rValue)
    {
        return lValue is TStock && rValue is TStock;
    }

    int IComparisonRule.Compare(Stock lValue, Stock rValue)
    {
        return Compare((TStock)lValue, (TStock)rValue);
    }

    public abstract int Compare(TStock lValue, TStock rValue);
}

现在,严格来说,您的问题是如何在不向下转换的情况下做到这一点,这(再次,严格来说)是不可能的。但是,这应该使您不必在每个实现中都这样做。例如,比较两个 AnotherStock 实例的简单规则是:

public class MyRule : ComparisonRule<AnotherStock>
{
    public override int Compare(AnotherStock lValue, AnotherStock rValue)
    {
        return lValue.someOtherProperty.CompareTo(rValue.someOtherProperty);
    }
}

在更高级别(即在Portfolio 内),您可以简单地将IComparisonRule 列表作为您的规则,然后您可以调用CanCompare 并传入两个Stock 实例以查看它是否是一个有效的比较,然后将它们传递给 Compare 以执行比较。

【讨论】:

  • 感谢您的详尽回答。
猜你喜欢
  • 2023-01-18
  • 2014-08-12
  • 1970-01-01
  • 2023-03-06
  • 2014-07-09
  • 1970-01-01
  • 2016-09-10
  • 1970-01-01
相关资源
最近更新 更多