Применение open closed principle на практике, c#

Всем привет.

Есть иерархия классов: продукт и классы, рассчитывающие налоги. Явным и наглым образом я тут нарушил OCP. Как решить эту проблему? В голову приходит только один вариант - создать интерфейсы-маркеры и ориентироваться по ним. Но это мне не нравится, ибо придется создавать кучу новых продуктовых классов в различных вариациях.

Спасибо!!!

public class Product
{
    public string Name { get; }
    public decimal Price { get; }
    public bool SupportsBasicSalesTax { get; }
    public bool SupportsImportDuty { get; }

    public Product(string name, decimal costs, bool supportsBasicSalesTax, bool supportsImportDuty)
    {
        Name = name;
        Price = costs;
        SupportsBasicSalesTax = supportsBasicSalesTax;
        SupportsImportDuty = supportsImportDuty;
    }
}

public class BasicSalesTax : ITax
{
    public const decimal Rate = 0.1m;

    public decimal Calculate(Product item)
    {
        return item.SupportsBasicSalesTax ? item.Price * Rate : 0;
    }
}

public class ImportDuty : ITax
{
    public const decimal Rate = 0.05m;

    public decimal Calculate(Product item)
    {
        return item.SupportsImportDuty ? item.Price * Rate : 0;
    }
}

Ответы (1 шт):

Автор решения: Роман Моргунов

Решил данный вопрос добавлением интерфейсов-маркеров: IImportProduct, IBasicProduct.

Класс, вычисляющий налог, проверял наличие реализации интерфейса.

Но есть также и другое решение (так сделал мой товарищ) - перечисление. Его решение я не видел. Я подразумеваю, что можно сделать свойство Taxes с типом перечисления Taxes. Самому перечислению нужно добавить атрибут, чтобы можно было применять несколько значений. А элементам этого перечисления давать значения степени 2.

Клоню к тому, что мы могли бы тогда применить несколько значений в одном свойстве.

→ Ссылка