这是我在当前项目中所面临问题的简化版本。
假设我们想要显示形状:矩形、圆圈等等。我将有一个形状类,它是由矩形、圆圈等子类组成的。然后我将有一个World类,它表示一个包含不同坐标下形状的2d平面。我将通过world.add(shape, x, y)向世界添加形状。这个世界对象和它的孩子应该完全不知道,我正计划在屏幕上显示他们。
现在我要展示这个。由于我可能会改变主意,我使用的图形库,我将有一个单独的Visualizer类。我用new Visualizer(world)创建一个,然后调用visualizer.show()。如果我更改图形库,我将创建一个不同的Visualizer类。
现在,这段代码中的某个地方是一个显示矩形的函数,另一个是显示圆圈的函数。他们应该去哪里?
Rectangle.library1Plot()、Rectangle.library2Plot()方法。.plotRectangle和.plotCircle方法,在创建更多的形状类型时添加越来越多的方法。这两种解决方案对我来说都不合适。
在代码中的某个地方,某人必须同时访问两条信息:形状是什么子类,以及我使用的图形库。哪里是最好的地方?
发布于 2018-05-24 12:58:44
如果形状类知道如何将自己绘制到某物上是可以接受的(而不知道下面使用的是哪个输出设备或图形库),那么您可以引入一个VisualizerInterface接口,该接口提供绘制简单线条和弧线的功能。
Visializer类将实现VisualizerInterface,并将绘制直线或弧线的函数转换为对特定图形库的正确调用。
Shape类将使用VisualizerInterface将自己绘制到任何可能的Vizualizer中,而不知道底层图形库。
Visualizer::show()方法可能类似于
Visualizer::show() {
foreach(shape in world.get_shapes()) {
shape.draw(this)
}
}其中,从形状派生的每个类都会重写绘图方法。
发布于 2018-05-24 12:51:00
我建议第三种选择:将描述形状的过程与绘制形状的过程分开。
有一个系统的描述一个形状的绘制,根据一个列表的直线和弧定义。然后,每个形状都有责任根据这些线定义来定义自己。
然后,可视化工具负责将一组线条描述转换为呈现的形状。
这样,形状就不需要知道任何关于如何呈现自己的信息,而可视化工具也不需要知道任何关于单个形状的信息。您完全避免了“代码中的某个位置,某人必须同时访问两个信息:形状是什么子类,以及我正在使用的图形库”的情况。可视化工具只在它提供的任何形状上调用shape.GetDrawingInstructions()。然后将耦合简化为一种方法,以及一组指令所采用的任何格式。
发布于 2018-05-24 17:35:59
我用模型/视图/视图模型(Model/ViewModel,MVVM)体系结构完成了您正在讨论的内容。只要您的呈现支持此设计模式(即支持绑定),它就可以工作。问题是,您将有许多您正在使用的视图。
模型代表被代表的事物。在我的例子中,它是一个映射应用程序。我们有特定于应用程序的对象和用户对象,它们帮助用户更好地总结地图。由于位置(即lat/lon)是模型的关键要素,我们在这里包括了这一点。
ViewModel负责诸如颜色之类的事情,在某些情况下切换表示(即表示某物的图标)。视图模型适用于不同类别的事物。也就是说,某物是地图上的一个特定点(针垫或自定义图标)、一个区域(多边形)、一条线还是一个椭圆。这些东西在我们的应用程序中有着特殊的意义,所以它们必须得到支持。
视图实际上负责在屏幕上呈现对象。这是唯一特定于平台的部分(即XAML与UAP相对于其他部分)。我们确实需要创建一个自定义面板来呈现控件(以及优化,这样它就不会在视图范围之外的事情上浪费时间)。
使这成为可能的是将属性从ViewModel和模型绑定到视图的能力。我们的代码存在于视图层中,这些代码将更具体的视图与相应的ViewModel匹配。
当然,这是大量的代码,但是如果您想在不显示映射的情况下运行模拟,这是可能的。您只需执行模型层和VieModel层。
如果您实际上需要有绘图指令,则另一个选项仍然是继续制作ViewModel,但是有一个抽象的Draw(Canvas)方法。然后,您必须为您需要的特定呈现代码对ViewModels进行子类化。或者,您可以创建一组原语,这些原语以绘图指令的形式组装。
作为绘制的一般规则,您可以使用以下2D原语:
你的3D等价物和那些基本形状没有太大的不同。
https://softwareengineering.stackexchange.com/questions/371474
复制相似问题