Единственный экземпляр вспомогательного объекта с параметрами - PullRequest
0 голосов
/ 10 января 2020

Один из наших проектов использует пары ключ-значение, в которых определенные параметры времени выполнения, которые не меняются в каждом конкретном случае программы, определяют полученное значение. Например:

Программа работает в режиме test с параметром "Municipal":

Key: "testMunicipalDirectory"
Value: "C:\Foo\Bar\"

Программа запускается с параметром "State":

Key: "StateDirectory"
Value: "C:\Bar\Baz\"

Чтобы сделать это немного сложнее, если нет подходящего ключа для, скажем, "testMunicipalImagesDirectory", есть запасной вариант "defaultImagesDirectory":

Key: "testMunicipalImagesDirectory" ?? "defaultImagesDirectory"
Value: "C:\Foo\Bar\Images" ?? "C:\Images"

В настоящее время существует много дублирования / неэффективности кода и места для ошибок. Каждый раз, когда на одну из них ссылаются, происходит конкатенация строк, объединение нулей и другие вещи.

Кажется, что это выиграет от объекта с одним экземпляром, которому передаются определенные параметры при инициализации (test или нет, "State" или "Municipal" и т. д. c), которые будут возвращать правильные значения для каждого отдельного свойства, которое представляют ключи.

Многие ответы, которые я нашел на вопросы, задающие вопрос об использовании шаблона проектирования Singleton с параметрами в основном сводятся к "если он использует параметры, вы, вероятно, не хотите синглтон". В моем случае недопустимо пытаться инициализировать объект с другими значениями, и в этом случае должно быть выдано исключение.

Так я бы достиг sh этой цели (псевдо- C#). ) (отложенная загрузка не обязательна, но используется здесь):

public sealed class Helper
{
    // how can we enforce that Init has been called?
    private static readonly Lazy<Helper> lazyLoader = new Lazy<Helper>(() => new Helper(name, test));

    public static Helper Instance { get { return lazyLoader.Value; } }

    public static void Init(string name, bool test)
    {
        // if it has already been initalized
        throw new InvalidOperationException("This has already been initalized.");
        // else initalize it
    }

    private string Name { get; set; }
    private bool   Test { get; set; }

    private Helper(string name, bool test) { } // assign to properties, any other ctor logic

    public string Directory
        { get { return ValueGetter.Get((this.Test ? "test" : "") + this.Name + "Directory"); } }
}

public static class ValueGetter
{
    public static string Get(string key, string fallbackKey)
    {
        if (Keys.Any(k => k == key))
            return Keys[key].Value;
        else
            return Keys[fallbackKey].Value;
    }
}

Но, как вы можете видеть, остаются вопросы. Как он может принудительно вызывать Init перед использованием Instance, но не требовать передачи этих параметров каждый время Instance доступа?

Это правильное направление к go, или есть лучший дизайн шаблона для использования?

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