首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >我应该有自动持久的实体吗?

我应该有自动持久的实体吗?
EN

Software Engineering用户
提问于 2017-12-15 11:33:16
回答 1查看 77关注 0票数 1

在MVVM应用程序(Xamarin.Forms,FWIW)中,我有一个视图模型,它显式地存储设置

代码语言:javascript
运行
复制
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对象时实例化的装饰器自动存储自己是否是个好主意

代码语言:javascript
运行
复制
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);
        }
    }
}

这将简化视图模型,并使保存设置变得透明。

代码语言:javascript
运行
复制
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的基本行为。

我是不是出了什么根本问题?我应该创建更多以用例为中心的设置类吗?我怎么可能做到这一点,因为我基本上有一个非常像数据的设置类视图。当涉及到设置时,这种方法是否完全合适?

EN

回答 1

Software Engineering用户

回答已采纳

发布于 2017-12-15 12:08:35

我认为没有问题的想法,有自我持久化设置。

但我真的不喜欢实现。首先,我将使用ISetting<T>属性创建T Value接口。然后,与bool SomeBoolSetting不同,我将拥有ISetting<bool> SomeBoolSetting并绑定到SomeBoolSetting.Value。这样,您就可以延迟加载您的设置,而不必在OnNavigated中手动加载,并且在基类中具有自动持久性,而不是在视图模型中的每个属性中调用UpdateSetting。这也简化了可能的装饰器,因为您只需要一种类型的装饰器。

快点破解我的意思。它假设ISettingRepository可以根据键保存和加载,而不是设置属性:

代码语言:javascript
运行
复制
  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
  }
票数 3
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/362443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档