首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有完全层分离和可测试性的观察者模式实现,我做得对吗?

具有完全层分离和可测试性的观察者模式实现,我做得对吗?
EN

Stack Overflow用户
提问于 2019-08-29 09:37:19
回答 2查看 190关注 0票数 0

我对我执行观察员模式有疑问,但完全分开关注。

下面的例子不是一个真实的生活代码,而是我想要做的一个例子。

在我的解决方案中,有两个项目层:

  • 桌面层(视图、视图模型、模型)
  • 服务库层(带观察者)

我的观点模型是一个订阅观察者的主题。

VM中的代码:

代码语言:javascript
复制
interface ISubject
{
    void Subscribe(IObserverService observer);
    void Unsubscribe(IObserverService observer);
    void Notify();
}
public class MainWindowViewModel : ViewModelBase, ISubject
{
    private readonly IObserverService _observer1;
    private readonly IObserverService _observer2;
    private ArrayList _observers;

    public MainWindowViewModel(
    IObserver1 observer1,
    IObserver2 observer2)
    {
        _observer1 = observer1;
        _observer2 = observer2;

        ObserverCommand = new DelegateCommand(OnObserverCommand);

        InitProgram();
    }

    private void InitProgram()
    {
        _observers = new ArrayList();

        _observers.Add(_observer1);
        _observers.Add(_observer2);
    }

    public List<IObserverService> Observers { get; set; }

    private void OnSwitchCommand(object obj)
    {
        if (Jeden == true)
        {
            UiModel = _controlsService.SwitchOff();
        }
        else
        {
            UiModel = _controlsService.SwitchOn();
        }
    }

    private void OnObserverCommand(object obj)
    {
        SomeValue++;
    }

    public void Subscribe(IObserverService observer)
    {
        Observers.Add(observer);
    }

    public void Unsubscribe(IObserverService observer)
    {
        Observers.Remove(observer);
    }

    public void Notify()
    {
        Observers.ForEach(x => x.Update(SomeValue));
    }

    public ICommand ObserverCommand { get; private set; }

    private int _someValue;
    public int SomeValue
    {
        get => _someValue;
        set
        {
            _someValue = value;
            InformObservers();
        }
    }

    private void InformObservers()
    {
        foreach (IObserverService x in _observers)
        {
            x.Update(SomeValue);
        }
    }
}

而我在服务层的观察者非常简单。在主题调用Update之后显示新的MessageBox

代码语言:javascript
复制
public interface IObserverService
{
    void Update(int someValue);
}
public class Observer1 : IObserver1, IObserverService
{
    public string ObserverName { get; private set; }
    public Observer1(string name)
    {
        this.ObserverName = name;
    }
    public void Update(int someValue)
    {
        MessageBox.Show("New value: " + someValue.ToString() + " for " + ObserverName);
    }
}

Observer2与上面相同。

现在,我怀疑构造函数应该是什么样的,如果我想创建一个带有name参数的新观察者,例如:在本例中是new Observer1("name1"),保持分离,我的主体的ctor看起来应该是:

代码语言:javascript
复制
public MainWindowViewModel()
{
     _observerService = observerService;
     IObserverService observer1 = new ObserverService("name1");
     IObserverService observer2 = new ObserverService("name2");

     SwitchCommnad = new DelegateCommand(OnSwitchCommand);
     ObserverCommand = new DelegateCommand(OnObserverCommand);

     InitProgram();
}

这样做正确吗?它会被测试吗?还是我要注射IObserverService?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-08-29 10:27:18

有道理的是,MainWindowViewModel将通过构造函数接收一些外部观察者:

代码语言:javascript
复制
public MainWindowViewModel(IObserver1 observer1, IObserver2 observer2)
{
    _observer1 = observer1;
    _observer2 = observer2;

    ObserverCommand = new DelegateCommand(OnObserverCommand);

    InitProgram();
}

当您创建一个MainWindowViewModel实例(我假设它将用于MainWindowView DataContext)时,您将传递一些真正的观察者:

代码语言:javascript
复制
 IObserverService observer1 = new ObserverService("name1");
 IObserverService observer2 = new ObserverService("name2");
 var vm = new MainWindowViewModel(observer1, observer2);
 mainWindow.DataContext = vm;

如果依赖项可以静态解析,则此处不需要DI容器。

类似地,对于测试,您可以使用一些TestObserverService (或IObserverService模拟):

代码语言:javascript
复制
 IObserverService observer1 = new TestObserverService("name1");
 IObserverService observer2 = new TestObserverService("name2");
 var vm = new MainWindowViewModel(observer1, observer2);

如果MainWindowViewModel具有从应用程序中的其他对象(例如相关视图模型)中值得观察的属性,它可能会创建一些IObserverServices。

票数 0
EN

Stack Overflow用户

发布于 2019-08-29 09:50:18

如果您想测试您的VM,请遵循IoC,不要在其中创建ObserverServices,但是正如您所说的,注入IObserverService;因此,您将能够模拟服务和测试VM,而不需要整个服务行为。

我可能建议你使用Autofac,甚至尼尼特。有大量的DI框架,所以寻找一个调整您要寻找的框架。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57707293

复制
相关文章

相似问题

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