希望避免在传递给Composite的策略中向下转发

时间:2011-08-21 00:20:57

标签: c# oop design-patterns

以下是我在金融行业的问题所在:

Asset
==========
Asset parent
assetID
+ compareTo(Asset anotherAsset)

Portfolio : Asset
-----------------
name
risk limit
List stocks
+ compareTo(Asset anotherAsset)
+ composite.CompareTo(Portfolio, ComparisonRules).

Stock : Asset
-------
market
amount
company
+ compareTo(Asset anotherAsset)

AnotherStock : Stock
--------------------
someOtherProperty
+ compareTo(Asset anotherAsset)

我已将复合模式应用于* Portfolio * s中的* Stock * s结构。我想有一个干净的方法来自定义此组合的compareTo方法。也就是说,AnotherStock将永远与另一个AnotherStock,Stocks to Stocks进行比较。这看起来像是我的战略模式。

我想做以下(psuedocode)

之类的事情
differences = composite.CompareTo(anotherComposite, ComparisonRules).

composite.CompareTo would be something like :

ComparisonRules.Compare(this.Stocks[currentAssetID], otherComposite[currentAssetID])

ComparisonRules.Compare(资产a,资产b)会做这样丑陋的事情:

if( a is Stock and b is Stock) : convert to stock and do stock-based comparison
else if (a is AnotherStock and b is AnotherSTock): convert to AnotherStock 

有没有办法以这样的方式编写ComparisonRules,我不需要向下转换,但仍然提供自定义的ComparisonRules对象?

1 个答案:

答案 0 :(得分:1)

从规则的角度来看,听起来你需要的是泛型。如果您沿着这些方向定义某些内容:

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

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

换句话说,你有这个:

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

这样您就可以定义一个可以将Stock作为ComparisonRule<Stock>进行比较的规则,或者只能将OneStockComparisonRule<OneStock>进行比较的规则。

但是,这并不能帮助您理清如何知道哪些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并传入两个{{ 1}}实例以查看它是否是有效的比较,然后将它们传递到Stock以执行比较。