存储对象图形信息的正确方法是什么?



我对OOP/设计模式很陌生,当涉及到将对象的逻辑信息与其图形状态分离时,我正在处理一个设计问题:

在Java音乐应用程序中,我试图使我有一个和弦类,它由注释类或Rest类组成。

在这些类中,我存储"逻辑"信息,如音符的midi值,其速度等。

我想在五线谱对象上绘制这些和弦(它扩展了某种GUI Panel对象):要做这样的事情,我需要在我的类中添加一些信息,例如我的对象在五线谱上的位置或它们的符号。

因此,我制作了我的类的图形"等效",保存这些图形信息,以及封装我的逻辑和弦,如下图所示:

https://i.stack.imgur.com/y4fQ3.png

但我坚持的东西,我认为是真的很奇怪:我的图表镜像在它的中心(这让我觉得我的图形类有点无用),我不能真正创建一个GraphicChord对象从Chord在运行,因为我不知道我是否应该做一个GraphicNoteGraphicRest为每个SimpleElement我的Chord包含…

我肯定有一些设计原则我一定做错了,但我找不到另一种方法来添加图形信息到我的对象…

你能帮我吗?

您正在处理两组不同的相关对象。你在图表中做得很好,有了基本的概念,但是,需要一些"清理"。

正如您已经看到的,一个组由存储数据或模型的对象组成。一个歌曲对象可以由几个音符组成。

另一组,表示数据或模型的可视化或图形化表示。你可以展示一个音乐五角星,它有几个部分,以及同一首歌的音符。

你可以使用"Decorator Software Design Pattern":

http://en.wikipedia.org/wiki/Decorator_pattern

But I'm stuck with something that I think is really strange :
my diagram is mirrored in its center
(which make me think my graphical classes are somewhat useless)
and I can't really create a GraphicChord object from a Chord
on the fly because I can't know if I should make a
GraphicNote or a GraphicRest for each SimpleElement my Chord contains...

在这种情况下,许多类被复制或"镜像"是没有问题的,因为一个组表示模型,而另一个组表示相同模型的可视化表示。

不要惊讶,如果别人说你错了,因为你有一个类的副本。在这种特殊情况下,信息的复制是正确的。

现在,关于你的问题,像一个非编程用户一样思考。非编程用户不考虑数据或模型类。他/她,考虑接口/GUI类,并与它们一起工作。

当用户(或您)创建一个和弦时,他/她实际上创建了一个GraphicalChord,而GraphicalChord将在幕后创建一个内部和弦。用户添加一个注释或Rest,并且实际上添加了一个图形注释或图形休息,并且,这些对象将创建一个数据注释或数据休息,并添加到Chord。

我建议给你的非图形类添加一个前缀或后缀,如"RealChord"、"DataChord"或类似的,以避免与GUI类混淆。

在"SimpleElement"的情况下,因为它已经知道它将有2个子类,你可以添加一个枚举属性来知道它是哪个类。

public enum ElementTypeEnum {
    UNASSIGNED,
    NOTE,
    REST
}
public class SimpleElementClass {
  private ElementTypeEnum _ElementType;
 public void setElementType(ElementTypeEnum n){
    _ElementType = n;
  }
  public ElementTypeEnum getElementType(){
    return _ElementType;
  }
  /* other members */
} // class SimpleElementClass
public class NoteClass extends SimpleElementClass { 
  /* other members */
} // class NoteClass
public class RestClass extends SimpleElementClass { 
  /* other members */
} // class RestClass 

这样,当您添加任何实现子类的对象时,您可以快速推断它是哪种类型。Chord类在某种程度上与"SimpleElementClass"类一起工作,而不是与子类一起工作。

欢呼

我不能动态地从一个Chord中创建一个GraphicChord对象因为我不知道应该为我的Chord包含的每个SimpleElement创建一个GraphicNote还是GraphicRest


如果这是使用图形对象的唯一原因,您可以使用instanceof来检查您拥有的SimpleElement类型。

if(myCurrentSimpleObject instanceof Note)
{
   // create Graphic object on the fly
}

如果你想避免使用instanceof,你可以通过添加一个抽象方法来改变你的SimpleElement类来确定对象类型。

 abstract boolean isNote();

子类必须实现这个方法并返回一个固定的true或false。通过返回描述类的枚举值,可以将其扩展到多个类。
如果您的子类有特定于它们的方法,您仍然需要将它们强制转换为正确的类。如果你想避免"未检查的类强制转换"编译器警告,而这样做,你仍然坚持与instanceof

相关内容

最新更新