Один из наших проектов использует пары ключ-значение, в которых определенные параметры времени выполнения, которые не меняются в каждом конкретном случае программы, определяют полученное значение. Например:
Программа работает в режиме 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, или есть лучший дизайн шаблона для использования?