在MVVM应用程序(Xamarin.Forms,FWIW)中,我有一个视图模型,它显式地存储设置
public class SettingsPageViewMode : INavigatedAware
{
ISettingsRepository settingsRepository; // injected
public void OnNavigatedTo(NavigationParameters navigationParameters)
{
var settings = settingsRepository.LoadSettings();
this.SomeBoolSetting = settings.SomeBoolSetting;
}
public bool SomeBoolSetting
{
get => someBoolSetting;
set
{
if(someBoolSetting == value)
{
return;
}
someBoolSetting = value;
OnPropertyChanged("SomeBoolSetting");
UpdateSettings();
}
}
private void UpdateSettings()
{
var settings = settingsRepository.LoadSettings();
settings.SomeBoolSetting = SomeBoolSetting;
settingsRepository.SaveSettings(settings);
}
}
我正在考虑让设置通过当ISettingsRepository
返回Settings
对象时实例化的装饰器自动存储自己是否是个好主意
internal class AutoPersistSettingsDecorator : Settings
{
Settings settings;
ISettingsRepository settingsRepository;
public AutoPersistSettingsDecorator(Settings settings, ISettingsRepository settingsRepository)
{
this.settings = settings;
this.settingsRepository = settingsRepository;
}
public override bool SomeBoolSetting
{
get => settings.SomeBoolSetting;
set
{
if(settings.SomeBoolSetting == value)
{
return;
}
settings.SomeBoolSetting = value;
settingsRepository.SaveSettings(settings);
}
}
}
这将简化视图模型,并使保存设置变得透明。
public class SettingsPageViewMode : INavigatedAware
{
ISettingsRepository settingsRepository; // injected
Settings settings;
public void OnNavigatedTo(NavigationParameters navigationParameters)
{
var settings = settingsRepository.LoadSettings();
this.SomeBoolSetting = settings.SomeBoolSetting;
}
public bool SomeBoolSetting
{
get => settings.SomeBoolSetting;
set
{
if(settings.SomeBoolSetting == value)
{
return;
}
settings.SomeBoolSetting = value;
OnPropertyChanged("SomeBoolSetting");
}
}
}
可能存在的缺陷:
Settings
看起来像一种数据类型,但附带了一种行为Settings
是持久化的Settings
的公共接口发生变化时,AutoPersistSettingsDecorator
也必须更改。然而,清洁代码仍然提出(或多或少)这个设计(我没有页码,因为我正在Kindle上阅读,但它在第11部分(系统)中,在关于AOP的部分中,就在图11-3之后)。
客户端认为它正在对一个
getAccounts()
对象调用Bank
,但实际上它正在与一组嵌套装饰对象对话,这些对象扩展了Bank
POJO的基本行为。
我是不是出了什么根本问题?我应该创建更多以用例为中心的设置类吗?我怎么可能做到这一点,因为我基本上有一个非常像数据的设置类视图。当涉及到设置时,这种方法是否完全合适?
发布于 2017-12-15 12:08:35
我认为没有问题的想法,有自我持久化设置。
但我真的不喜欢实现。首先,我将使用ISetting<T>
属性创建T Value
接口。然后,与bool SomeBoolSetting
不同,我将拥有ISetting<bool> SomeBoolSetting
并绑定到SomeBoolSetting.Value
。这样,您就可以延迟加载您的设置,而不必在OnNavigated中手动加载,并且在基类中具有自动持久性,而不是在视图模型中的每个属性中调用UpdateSetting
。这也简化了可能的装饰器,因为您只需要一种类型的装饰器。
快点破解我的意思。它假设ISettingRepository
可以根据键保存和加载,而不是设置属性:
public interface ISetting<T> : INotifyPropertyChanged
{
T Value { get; set; }
}
public interface ISettingsRepository
{
void SaveSetting(string name, object value);
object LoadSettings(string name);
}
public class PersistedSetting<T> : ISetting<T>
{
private T _value;
bool hasValue;
private readonly ISettingsRepository _repository;
private readonly string _key;
public PersistedSetting(ISettingsRepository repository, string key)
{
_repository = repository;
_key = key;
}
public T Value
{
get
{
if (!hasValue)
{
// lazy loaded
_value = (T)_repository.LoadSettings(_key);
}
return _value;
}
set
{
if (hasValue && _value.Equals(value))
{
return; // dont update if same
}
_value = value;
_repository.SaveSetting(_key, _value); // persisted every time it changed
hasValue = true;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class SettingsPageViewMode
{
ISettingsRepository settingsRepository;
// seriously here. Use constructor injection
public SettingsPageViewMode(ISettingsRepository settingsRepository)
{
this.settingsRepository = settingsRepository;
SomeBoolSetting = new PersistedSetting<bool>(settingsRepository, "SomeBool");
}
public ISetting<bool> SomeBoolSetting { get; } // bind to SomeBoolSetting.Value
}
https://softwareengineering.stackexchange.com/questions/362443
复制相似问题