Prosty sposób na zachowanie ustawień aplikacji Java jest reprezentowany przez plik tekstowy z rozszerzeniem „.properties” zawierający identyfikator każdego ustawienia powiązanego z określoną wartością (ta wartość może być liczbą, łańcuchem, datą itp.) . C # stosuje podobne podejście, ale plik tekstowy musi mieć nazwę „App.config”. W obu przypadkach w kodzie źródłowym należy zainicjować określoną klasę do odczytu ustawień: ta klasa ma metodę, która zwraca wartość (jako ciąg) powiązaną z określonym identyfikatorem ustawienia.
// Java example
Properties config = new Properties();
config.load(...);
String valueStr = config.getProperty("listening-port");
// ...
// C# example
NameValueCollection setting = ConfigurationManager.AppSettings;
string valueStr = setting["listening-port"];
// ...
W obu przypadkach powinniśmy przeanalizować ciągi znaków załadowane z pliku konfiguracyjnego i przypisać przekonwertowane wartości do powiązanych obiektów tekstowych (podczas tej fazy mogą wystąpić błędy analizy). Po etapie analizy musimy sprawdzić, czy wartości ustawień należą do konkretnej dziedziny ważności: na przykład maksymalny rozmiar kolejki powinien być wartością dodatnią, niektóre wartości mogą być powiązane (przykład: min <max ), i tak dalej.
Załóżmy, że aplikacja powinna załadować ustawienia, jak tylko się uruchomi: innymi słowy, pierwszą operacją wykonywaną przez aplikację jest załadowanie ustawień. Wszelkie nieprawidłowe wartości ustawień muszą zostać automatycznie zastąpione wartościami domyślnymi: jeśli tak się stanie z grupą powiązanych ustawień, wszystkie te ustawienia zostaną ustawione na wartości domyślne.
Najłatwiejszym sposobem na wykonanie tych operacji jest stworzenie metody, która najpierw analizuje wszystkie ustawienia, a następnie sprawdza załadowane wartości i ostatecznie ustawia wartości domyślne. Jednak konserwacja jest trudna, jeśli zastosujesz to podejście: wraz ze wzrostem liczby ustawień podczas opracowywania aplikacji coraz trudniej jest zaktualizować kod.
Aby rozwiązać ten problem, pomyślałem o użyciu wzorca metody szablonu w następujący sposób.
public abstract class Setting
{
protected abstract bool TryParseValues();
protected abstract bool CheckValues();
public abstract void SetDefaultValues();
/// <summary>
/// Template Method
/// </summary>
public bool TrySetValuesOrDefault()
{
if (!TryParseValues() || !CheckValues())
{
// parsing error or domain error
SetDefaultValues();
return false;
}
return true;
}
}
public class RangeSetting : Setting
{
private string minStr, maxStr;
private byte min, max;
public RangeSetting(string minStr, maxStr)
{
this.minStr = minStr;
this.maxStr = maxStr;
}
protected override bool TryParseValues()
{
return (byte.TryParse(minStr, out min)
&& byte.TryParse(maxStr, out max));
}
protected override bool CheckValues()
{
return (0 < min && min < max);
}
public override void SetDefaultValues()
{
min = 5;
max = 10;
}
}
Problem polega na tym, że w ten sposób musimy stworzyć nową klasę dla każdego ustawienia, nawet dla pojedynczej wartości. Czy istnieją inne rozwiązania tego rodzaju problemu?
W podsumowaniu:
- Łatwa konserwacja: na przykład dodanie jednego lub więcej parametrów.
- Rozszerzalność: pierwsza wersja aplikacji może odczytać pojedynczy plik konfiguracyjny, ale późniejsze wersje mogą dawać możliwość konfiguracji dla wielu użytkowników (administrator konfiguruje konfigurację podstawową, użytkownicy mogą konfigurować tylko niektóre ustawienia itp.).
- Projektowanie obiektowe.