Хотите избежать даункинга внутри Стратегии, переданной в Композит - PullRequest
2 голосов
/ 21 августа 2011

Вот моя проблемная область в финансовой индустрии:

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)

Я применил составной шаблон к структуре * Фондовая * с в пределах * Портфель *s.Я хочу иметь чистый способ настройки метода CompareTo этого композита.То есть, AnotherStock всегда будет сравниваться с другим AnotherStock, Акции с Акциями.Для меня это выглядит как шаблон стратегии.

Я хотел бы сделать что-то вроде следующего (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 Ответ

1 голос
/ 21 августа 2011

С точки зрения правил звучит так, как будто вам нужны дженерики.Если вы определите что-то вроде этих строк:

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>, или правило, которое может сравнивать только OneStock как ComparisonRule<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 и передать два Stock экземпляра, чтобы проверить, является ли это допустимым сравнением, а затем передать их в Compare для выполнения сравнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...