如何分别观察一个界面的不同概念?
基本上,我想做的是拥有一个通用的模拟器界面,它充当模型和用户界面(充当视图)之间的耦合。我的模拟器界面如下所示:
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是其实际值的类型(例如
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#.
实际上,我希望这个接口表明充当模拟运行数据的集合和模拟器本身都是可单独观察的。最后,我希望用户界面的一部分显示当前数据(例如矩阵),另一部分显示和控制模拟器,并带有一些按钮,如“运行”、“停止”、“重置”等由于模拟器也可能通过其他方式停止,而不仅仅是单击按钮(例如,在达到某些特定状态、生成等之后),因此该控件也需要来自模拟器的更新,但不是数据状态的更新,但模拟器本身。
不可能使我编写的集合接口可观察,因为该集合在模拟期间不会被修改,而是通过应用函数进行转换,并且转换将产生一个新的集合,然后模拟器将其存储(并通知收藏的观察者)。
我该怎么办?
- 打破不变性概念 始终保留相同的集合(在 身份条款,不包含 值)随着时间的推移而改变 而不是生产新的、修改过的 收藏品?
- 打破耦合并拥有我的用户 接口知道确切的 实施这将在外部 的接口,提供第二个 意味着观察模拟器 本身?拥有所有用户界面 需要更新的组件 模拟器观察整体 东西,不只是相关数据?
- 创建一个单独的接口 观察收藏,并拥有我的 模拟器实现工具 两个接口?
- 还有别的事吗?
Basically, what I am trying to do is have a generic simulator-interface which acts as the lose coupling between the model and the user interface, which acts as the view. My simulator interface looks like this:
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 is the type of a data collection, 'Item is the type of a single data item, and 'Value is the type of its actual value (for example <Matrix, Cell, float>, <Tree, Node, string> etc.). Now, the line
inherit System.IObservable<ISimulator<'Collection, 'Item, 'Value>>
produces an error:
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#.
Effectively, I want this interface to say that both the Collection which serves as the data the simulation is running upon and the Simulator itself to be observable separately. In the end, I want a part of my user interface to display the current data (for example a matrix) and a different part to display and control the simulator, with some buttons like "run", "stop", "reset" etc. Since the simulator might also be stopped by other means than just clicking a button (for example, after reaching some specific state, generation etc.), that control needs updates from the simulator, too, but not on the state of the data, but the simulator itself.
It is not possible to make the collection interface I would write observable, as that collection wouldn't be modified during simulation, but transformed by applying a function, and the transformation would produce a new collection, which the simulator then stores (and notifies the observers of the collection).
What shall I do?
- Break the immutability concept and
always keep the same collection (in
terms of identity, not contained
values) which just changes over time
instead of producing new, modified
collections? - Break lose coupling and have my user
interface know the exact
implementation which would, outside
of the interface, provide a second
means to observer the simulator
itself? Have all user interface
components which require updates from
the simulator observe the whole
thing, not just the relevant data? - Create a seperate interface to
observe the collection, and have my
simulator implementation implement
both interfaces? - Something else?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您是否考虑过通过属性来公开可观察量,就像传统事件一样?
这使得消费者能够明确他们正在观察哪些行为。
Have you considered exposing the observables through properties, sort of like traditional events?
This allows consumers to be explicit about which behavior they're observing.
开始吧,我做了 IObservable 的简单实现,然后根据 dahlbyk 提供的接口定义公开了公共属性。我在 这个网站 并从那里概括了一点:
包含此实现实例作为属性的类只是将其视为
Observable<'a>
对象,而对其其他人来说,它仅作为IObservable<'a>
接口公开。我认为这在松散耦合方面很好,并且仍然允许在观察者/可观察对的任一端非常简单地使用。PS:这也是我喜欢 F# 的原因 - 如果用 C++ 这样的语言来实现整个结构将是一团糟;但在这里我可以将一个函数传递到另一个函数中,以便将其应用于所有观察者。 :)
Here we go, I made this bare-bones implementation of IObservable, of which I then expose public properties according to the interface definition dahlbyk provided. I've found the basic idea for this implementation on this website and generalized a bit from there:
The class containing instances of this implementation as properties just treats it as an
Observable<'a>
object, while to everyone else it is exposed only as anIObservable<'a>
interface. I think this is nice in terms of loose coupling and still allows very straightforward usage on either end of the Observer/Observable pair.P.S.: This is also why I love F# - this entire construct would be a total mess to implement in a language like C++; but here I can just pass a function into another function in order to apply it on all observers. :)