GRASP之纯粹的制作模式 - Kamil Grzybek


问题:什么对象应该有责任,当你不想使高凝聚力和低耦合时,但其他原则提供的解决方案不合适?
解决方案:将一组高度凝聚力的责任分配给脚手架或帮助类之类工具,这些工具并不代表问题域中的概念。
有时候很难弄清楚应该在哪里放置责任。这就是领域驱动设计中存在领域服务概念的原因。领域服务保存与一个特定实体无关的逻辑。
例如,在电子商务系统中,我们经常需要将一种货币转换为另一种货币。有时很难说这种行为应该放在哪里,所以最好的选择是创建新的类和接口:

public interface IForeignExchange
{
    List<ConversionRate> GetConversionRates();
}

public class ForeignExchange : IForeignExchange
{
    private readonly ICacheStore _cacheStore;

    public ForeignExchange(ICacheStore cacheStore)
    {
        _cacheStore = cacheStore;
    }

    public List<ConversionRate> GetConversionRates()
    {
        var ratesCache = this._cacheStore.Get(new ConversionRatesCacheKey());

        if (ratesCache != null)
        {
            return ratesCache.Rates;
        }

        List<ConversionRate> rates = GetConversionRatesFromExternalApi();

        this._cacheStore.Add(new ConversionRatesCache(rates), new ConversionRatesCacheKey(), DateTime.Now.Date.AddDays(1));

        return rates;
    }

    private static List<ConversionRate> GetConversionRatesFromExternalApi()
    {
        // Communication with external API. Here is only mock.

        var conversionRates = new List<ConversionRate>();

        conversionRates.Add(new ConversionRate(
"USD", "EUR", (decimal)0.88));
        conversionRates.Add(new ConversionRate(
"EUR", "USD", (decimal)1.13));

        return conversionRates;
    }
}

这样我们就支持高聚合High Cohesion(我们只转换货币)和低耦合Low Coupling(客户端类只依赖于 IForeignExchange 接口)。此外,该类可重用且易于维护。