Получить экземпляр того же типа, используя полиморфизм - PullRequest
0 голосов
/ 10 апреля 2020

У меня следующий сценарий: есть класс, отвечающий за управление всеми валютами приложения. Все валюты расширяют валюту, поэтому она может вести себя так, как она. Валюта абстрактна, поэтому ее невозможно создать. В некоторых частях приложения в качестве валюты стоимости у меня есть мягкая, жесткая валюта или валюта события, например, игрок нажимает кнопку покупки в каком-то меню. Это действие инициирует покупку, покупка имеет валюту в качестве ссылки, в этом примере это может быть costSoftCurrency. Идея состоит в том, что если PlayerCurrencies получают валюту, валюты игрока оценивают его валюты и возвращают соответствующую валюту того же типа, а затем вы можете безопасно вычесть стоимость.

Мой вопрос ... как я могу получить те же логи c без этого ужасного ifs? Я читал о двойной отправке , но я не знаю, можно ли это здесь применить.

Кто-нибудь знает, можно ли этого достичь?

public class PlayerCurrencies
{
    public SoftCurrency softCurrency = new SoftCurrency();
    public HardCurrency hardCurrency = new HardCurrency();
    public EventCurrency eventCurrency = new EventCurrency();

    public Currency GetCurrencyFromType(Currency currency)
    {
        if (currency is SoftCurrency)
        {
            return this.softCurrency;
        }

        if (currency is HardCurrency)
        {
            return this.hardCurrency;
        }

        if (currency is EventCurrency)
        {
            return this.eventCurrency;
        }

        return null;
    }
}

public abstract class Currency
{
    public float Value
    {
        get;
        set;
    }

    public void Add(Currency currency)
    {
        this.Value += currency.Value;
    }

    public void Substract(Currency currency)
    {
        this.Value -= currency.Value;
    }
}

public class EventCurrency : Currency
{

}

public class HardCurrency : Currency
{

}

public class SoftCurrency : Currency
{

}

internal class Program
{
    private static void Main(string[] args)
    {
        PlayerCurrencies playerCurrencies = new PlayerCurrencies();

        Currency costSoftCurrency = new SoftCurrency();
        Currency costHardCurrency = new HardCurrency();

        playerCurrencies.GetCurrencyFromType(costSoftCurrency).Substract(costSoftCurrency); // there i get a SoftCurrency from Player Currencies 
        playerCurrencies.GetCurrencyFromType(costHardCurrency).Substract(costHardCurrency); // there i get a HardCurrency from Player Currencies 
    }
}

Ответы [ 2 ]

1 голос
/ 10 апреля 2020

Я бы использовал для этого шаблон проектирования метода фабрики, так как это специально для случаев, когда вы используете подклассы, чтобы выяснить, какие классы должны быть созданы. Это в основном то, что вы делаете здесь. В моем первоначальном ответе упоминалось отражение, потому что я увидел конфигурацию сопоставления на веб-сайте, на который я ссылаюсь, и подумал, что это круто, но после обдумывания вчерашнего вечера у него также много накладных расходов. Было бы намного проще и быстрее обойти оператор if block или switch с помощью словаря.

Вот что я хотел бы добавить / изменить в вашем коде:

//The Factory class that creates the different types of currency based
//on a name parameter
static class CurrencyFactory
{
    private static readonly Dictionary<string, Currency> _currencyDictionary =
        new Dictionary<string, Currency>
    {
        { "HardCurrency", new HardCurrency() },
        { "SoftCurrency", new SoftCurrency() },
        { "EventCurrency", new EventCurrency() }
    };

    public static Currency Create(string currencyTypeName)
    {
        return _currencyDictionary[currencyTypeName];
    }
}

internal class Program
{
    private static void Main(string[] args)
    {
        //This class will no longer be needed as it is redundant
        PlayerCurrencies playerCurrencies = new PlayerCurrencies();

        var costSoftCurrency = CurrencyFactory.Create("softCurrency");
        var costHardCurrency = CurrencyFactory.Create("hardCurrency");

        //I wasn't sure of your goals here so I kept it as is,
        //but as I said above, playerCurrencies won't be needed.
        playerCurrencies.GetCurrencyFromType(costSoftCurrency)
            .Substract(costSoftCurrency); // there i get a SoftCurrency from Player Currencies 

        playerCurrencies.GetCurrencyFromType(costHardCurrency)
            .Substract(costHardCurrency); // there i get a HardCurrency from Player Currencies 
    }
}

Вы можете найдите более подробный пример и отличное объяснение модели здесь: https://dev.to/gary_woodfine/how-to-use-factory-method-design-pattern-in-c-3ia3

0 голосов
/ 10 апреля 2020

Это можно сделать с помощью сопоставления с образцом :

public class PlayerCurrencies
{
    public SoftCurrency Soft = new SoftCurrency();
    public HardCurrency Hard = new SoftCurrency();
    public EventCurrency Event = new EventCurrency();

    public Currency GetCurrencyFromType(Currency currency)
    {
        switch (currency)
        {
            case EventCurrency: return Event;
            case HardCurrency: return Hard;
            case SoftCurrency: return Soft;
        }
        return null;
    }
}

Я изменил имена полей на Hard, Soft и Event, чтобы их было легче различить guish их из типов с одинаковыми именами.

В этом конкретном примере кажется странным передавать параметр currency и использовать его только для своего типа. Там может быть другой способ решить вашу конкретную проблему c. Но что касается того, как сделать это без нескольких операторов if, это то, как вы можете это сделать.

Чаще всего это будет продемонстрировано с объявленными переменными следующим образом:

switch (currency)
{
    case EventCurrency ec : return Event;
    case HardCurrency hc: return Hard;
    case SoftCurrency sc: return Soft;
}
return null;

Например, если тип currency был EventCurrency, то в области действия case, ec будет аргументом currency, приведенным к EventCurrency. Но поскольку в этом примере вы не используете значение, переменные не нужны.

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