代码之家  ›  专栏  ›  技术社区  ›  Mephane

如何分别观察一个接口的不同概念?

  •  2
  • Mephane  · 技术社区  · 14 年前

    基本上,我要做的是拥有一个通用的模拟器接口,它充当模型和用户接口之间的丢失耦合,用户接口充当视图。我的模拟器界面如下:

    type ISimulator<'Collection, 'Item, 'Value> =
      inherit System.IObservable<'Collection>
      inherit System.IObservable<ISimulator<'Collection, 'Item, 'Value>>
      abstract Start:           unit -> unit
      abstract Stop:            unit -> unit
      abstract Reset:           unit -> unit
      abstract Reset:           'Collection -> unit
      abstract Advance:         int<gen> -> unit
      abstract InitialState:    'Collection
        with get
      abstract CurrentState:    'Collection
        with get
      abstract Rule:            ('Item -> 'Value)
        with get, set
      abstract Generation:      int<gen>
        with get, set
      abstract Speed:           float<gen/sec>
        with get, set
      abstract Running:         bool
        with get
    

    “collections是数据集合的类型,”“item是单个数据项的类型,value是其实际值的类型(例如<matrix、cell、float>、<tree、node、string>等)。现在,这条线

    inherit System.IObservable<ISimulator<'Collection, 'Item, 'Value>>
    

    产生错误:

    This type implements or inherits the same interface at different generic instantiations 'System.IObservable<Interface.ISimulator<'Collection,'Item,'Value>>' and 'System.IObservable<'Collection>'. This is not permitted in this version of F#.
    

    实际上,我想让这个接口说,作为模拟运行数据的收集和模拟器本身都是可以单独观察的。最后,我希望我的用户界面的一部分显示当前数据(例如矩阵),另一部分显示和控制模拟器,使用一些按钮,如“运行”、“停止”、“重置”等,因为模拟器也可以通过其他方式停止,而不仅仅是单击一个按钮(例如,在达到某个特定状态后,General控制也需要模拟器的更新,但不是数据的状态,而是模拟器本身。

    不可能使我将编写的收集接口成为可观察的,因为在模拟过程中不会修改该收集,而是通过应用函数进行转换,并且转换将生成一个新的收集,然后模拟器将其存储(并通知收集的观察者)。

    我该怎么办?

    • 打破不变概念 始终保持相同的收藏(在 身份条款,未包含 值)随时间变化 而不是生产新的,改良的 收藏?
    • 断开失去耦合并让我的用户 界面知道确切的 在外部实施 在接口中,提供一秒钟 观察模拟器的方法 本身?拥有所有用户界面 需要更新的组件 模拟器观察整个 事情,而不仅仅是相关数据?
    • 创建一个单独的接口 观察收藏,并让我 模拟器实现 两个接口?
    • 还有别的吗?
    2 回复  |  直到 10 年前
        1
  •  3
  •   dahlbyk    14 年前

    type ISimulator<'Collection, 'Item, 'Value> =
      abstract Items:           System.IObservable<'Collection>
      abstract Control:         System.IObservable<ISimulator<'Collection, 'Item, 'Value>>
      abstract Start:           unit -> unit
      ...
    

        2
  •  0
  •   Mephane    14 年前

    this website

      open System
    
      type Observable<'a>() =
        let mutable _observers: List<IObserver<'a>> = []
        let Notify func =
          _observers
          |> Seq.map(fun (observer: IObserver<'a>) -> async { return func observer} )
          |> Async.Parallel
          |> Async.RunSynchronously
          |> ignore
    
        interface IObservable<'a> with
    
          member this.Subscribe (observer: IObserver<'a>) =
            _observers <- observer :: _observers
            { new IDisposable with
                  member this.Dispose() =
                    _observers <- _observers |> List.filter((<>) observer) }
    
        member this.Next value =
          Notify(fun (observer: IObserver<'a>) -> observer.OnNext value)
    
        member this.Error error =
          Notify(fun (observer: IObserver<'a>) -> observer.OnError error)
    
        member this.Completed() =
          Notify(fun (observer: IObserver<'a>) -> observer.OnCompleted)
    

    Observable<'a> 对象,而对其他所有人来说,它只作为 IObservable<'a> 接口。我认为这在松耦合方面是很好的,并且仍然允许在观察者/可观测对的任一端使用非常直接的方法。

    P.S.:这也是为什么我喜欢F.Y-这整个构造将是一个完全混乱的语言,如C++,但在这里,我可以通过一个函数到另一个函数,以便将其应用于所有观察员。:)